Commit 958b5237 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Store texture sub-resources in IWineD3DBaseTextureClass.

parent 11c7a67a
......@@ -27,9 +27,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DRESOURCETYPE resource_type,
IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct wined3d_format_desc *format_desc,
WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT layer_count, UINT level_count,
WINED3DRESOURCETYPE resource_type, IWineD3DDeviceImpl *device, UINT size, DWORD usage,
const struct wined3d_format_desc *format_desc, WINED3DPOOL pool, IUnknown *parent,
const struct wined3d_parent_ops *parent_ops)
{
HRESULT hr;
......@@ -41,7 +42,17 @@ HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DR
return hr;
}
texture->baseTexture.levels = levels;
texture->baseTexture.sub_resources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
level_count * layer_count * sizeof(*texture->baseTexture.sub_resources));
if (!texture->baseTexture.sub_resources)
{
ERR("Failed to allocate sub-resource array.\n");
resource_cleanup((IWineD3DResource *)texture);
return E_OUTOFMEMORY;
}
texture->baseTexture.layer_count = layer_count;
texture->baseTexture.level_count = level_count;
texture->baseTexture.filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE;
texture->baseTexture.LOD = 0;
texture->baseTexture.texture_rgb.dirty = TRUE;
......@@ -66,6 +77,7 @@ HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DR
void basetexture_cleanup(IWineD3DBaseTexture *iface)
{
basetexture_unload(iface);
HeapFree(GetProcessHeap(), 0, ((IWineD3DBaseTextureImpl *)iface)->baseTexture.sub_resources);
resource_cleanup((IWineD3DResource *)iface);
}
......@@ -115,8 +127,8 @@ DWORD basetexture_set_lod(IWineD3DBaseTexture *iface, DWORD LODNew)
return 0;
}
if(LODNew >= This->baseTexture.levels)
LODNew = This->baseTexture.levels - 1;
if (LODNew >= This->baseTexture.level_count)
LODNew = This->baseTexture.level_count - 1;
if(This->baseTexture.LOD != LODNew) {
This->baseTexture.LOD = LODNew;
......@@ -145,8 +157,8 @@ DWORD basetexture_get_lod(IWineD3DBaseTexture *iface)
DWORD basetexture_get_level_count(IWineD3DBaseTexture *iface)
{
IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
TRACE("(%p) : returning %d\n", This, This->baseTexture.levels);
return This->baseTexture.levels;
TRACE("iface %p, returning %u.\n", iface, This->baseTexture.level_count);
return This->baseTexture.level_count;
}
HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType)
......@@ -301,10 +313,11 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface, BOOL srgb, BOOL *set_surfac
* relying on the partial GL_ARB_texture_non_power_of_two emulation with texture rectangles
* (ie, do not care for cond_np2 here, just look for GL_TEXTURE_RECTANGLE_ARB)
*/
if(textureDimensions != GL_TEXTURE_RECTANGLE_ARB) {
TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");
if (textureDimensions != GL_TEXTURE_RECTANGLE_ARB)
{
TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", This->baseTexture.level_count - 1);
glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.level_count - 1);
checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.level_count)");
}
if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) {
/* Cubemaps are always set to clamp, regardless of the sampler state. */
......@@ -444,17 +457,18 @@ void basetexture_apply_state_changes(IWineD3DBaseTexture *iface,
glTexParameteri(textureDimensions, GL_TEXTURE_MIN_FILTER, glValue);
checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
if(!cond_np2) {
if(gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE) {
if (!cond_np2)
{
if (gl_tex->states[WINED3DTEXSTA_MIPFILTER] == WINED3DTEXF_NONE)
glValue = This->baseTexture.LOD;
} else if(gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.levels) {
glValue = This->baseTexture.levels - 1;
} else if(gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < This->baseTexture.LOD) {
else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] >= This->baseTexture.level_count)
glValue = This->baseTexture.level_count - 1;
else if (gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL] < This->baseTexture.LOD)
/* baseTexture.LOD is already clamped in the setter */
glValue = This->baseTexture.LOD;
} else {
else
glValue = gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL];
}
/* Note that D3DSAMP_MAXMIPLEVEL specifies the biggest mipmap(default 0), while
* GL_TEXTURE_MAX_LEVEL specifies the smallest mimap used(default 1000).
* So D3DSAMP_MAXMIPLEVEL is the same as GL_TEXTURE_BASE_LEVEL.
......
......@@ -479,9 +479,8 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, struct
if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
{
IWineD3DSurfaceImpl *surf;
surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)stateblock->textures[0];
IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0];
if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
{
......@@ -3097,9 +3096,8 @@ void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d
if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
{
IWineD3DSurfaceImpl *surf;
surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)stateblock->textures[0];
IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0];
if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
{
......
......@@ -2771,8 +2771,8 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
{
IWineD3DSurfaceImpl *surf;
surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *)stateblock->textures[0];
IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *)texture->baseTexture.sub_resources[0];
if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
{
......
......@@ -51,17 +51,19 @@ static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINE
* since the last load then reload the volumes. */
if (This->baseTexture.texture_rgb.dirty)
{
for (i = 0; i < This->baseTexture.levels; ++i)
for (i = 0; i < This->baseTexture.level_count; ++i)
{
IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode);
IWineD3DVolume *volume = (IWineD3DVolume *)This->baseTexture.sub_resources[i];
IWineD3DVolume_LoadTexture(volume, i, srgb_mode);
}
}
else if (srgb_was_toggled)
{
for (i = 0; i < This->baseTexture.levels; ++i)
for (i = 0; i < This->baseTexture.level_count; ++i)
{
volume_add_dirty_box(This->volumes[i], NULL);
IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode);
IWineD3DVolume *volume = (IWineD3DVolume *)This->baseTexture.sub_resources[i];
volume_add_dirty_box(volume, NULL);
IWineD3DVolume_LoadTexture(volume, i, srgb_mode);
}
}
else
......@@ -81,9 +83,9 @@ static void volumetexture_cleanup(IWineD3DVolumeTextureImpl *This)
TRACE("(%p) : Cleaning up.\n", This);
for (i = 0; i < This->baseTexture.levels; ++i)
for (i = 0; i < This->baseTexture.level_count; ++i)
{
IWineD3DVolume *volume = This->volumes[i];
IWineD3DVolume *volume = (IWineD3DVolume *)This->baseTexture.sub_resources[i];
if (volume)
{
......@@ -172,8 +174,9 @@ static void WINAPI IWineD3DVolumeTextureImpl_UnLoad(IWineD3DVolumeTexture *iface
* surface before, this one will be a NOP and vice versa. Unloading an unloaded
* surface is fine
*/
for (i = 0; i < This->baseTexture.levels; i++) {
IWineD3DVolume_UnLoad(This->volumes[i]);
for (i = 0; i < This->baseTexture.level_count; ++i)
{
IWineD3DVolume_UnLoad((IWineD3DVolume *)This->baseTexture.sub_resources[i]);
}
basetexture_unload((IWineD3DBaseTexture *)iface);
......@@ -250,65 +253,85 @@ static BOOL WINAPI IWineD3DVolumeTextureImpl_IsCondNP2(IWineD3DVolumeTexture *if
/* *******************************************
IWineD3DVolumeTexture IWineD3DVolumeTexture parts follow
******************************************* */
static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTexture *iface, UINT Level,WINED3DVOLUME_DESC *pDesc) {
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
if (Level < This->baseTexture.levels) {
TRACE("(%p) Level (%d)\n", This, Level);
return IWineD3DVolume_GetDesc(This->volumes[Level], pDesc);
} else {
WARN("(%p) Level (%d)\n", This, Level);
static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTexture *iface,
UINT level, WINED3DVOLUME_DESC *desc)
{
IWineD3DVolumeTextureImpl *texture = (IWineD3DVolumeTextureImpl *)iface;
TRACE("iface %p, level %u, desc %p.\n", iface, level, desc);
if (level >= texture->baseTexture.level_count)
{
WARN("level %u >= level_count %u.\n", level, texture->baseTexture.level_count);
return WINED3DERR_INVALIDCALL;
}
return WINED3D_OK;
return IWineD3DVolume_GetDesc((IWineD3DVolume *)texture->baseTexture.sub_resources[level], desc);
}
static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetVolumeLevel(IWineD3DVolumeTexture *iface, UINT Level, IWineD3DVolume** ppVolumeLevel) {
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
if (Level < This->baseTexture.levels) {
*ppVolumeLevel = This->volumes[Level];
IWineD3DVolume_AddRef(*ppVolumeLevel);
TRACE("(%p) -> level(%d) returning volume@%p\n", This, Level, *ppVolumeLevel);
} else {
WARN("(%p) Level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetVolumeLevel(IWineD3DVolumeTexture *iface,
UINT level, IWineD3DVolume **volume)
{
IWineD3DVolumeTextureImpl *texture = (IWineD3DVolumeTextureImpl *)iface;
TRACE("iface %p, level %u, volume %p.\n", iface, level, volume);
if (level >= texture->baseTexture.level_count)
{
WARN("level %u >= level_count %u.\n", level, texture->baseTexture.level_count);
return WINED3DERR_INVALIDCALL;
}
*volume = (IWineD3DVolume *)texture->baseTexture.sub_resources[level];
IWineD3DVolume_AddRef(*volume);
TRACE("Returning volume %p.\n", *volume);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DVolumeTextureImpl_LockBox(IWineD3DVolumeTexture *iface, UINT Level, WINED3DLOCKED_BOX* pLockedVolume, CONST WINED3DBOX* pBox, DWORD Flags) {
HRESULT hr;
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
if (Level < This->baseTexture.levels) {
hr = IWineD3DVolume_LockBox(This->volumes[Level], pLockedVolume, pBox, Flags);
TRACE("(%p) Level (%d) success(%u)\n", This, Level, hr);
static HRESULT WINAPI IWineD3DVolumeTextureImpl_LockBox(IWineD3DVolumeTexture *iface,
UINT level, WINED3DLOCKED_BOX *locked_box, const WINED3DBOX *box, DWORD flags)
{
IWineD3DVolumeTextureImpl *texture = (IWineD3DVolumeTextureImpl *)iface;
} else {
FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
TRACE("iface %p, level %u, locked_box %p, box %p, flags %#x.\n",
iface, level, locked_box, box, flags);
if (level >= texture->baseTexture.level_count)
{
WARN("level %u >= level_count %u.\n", level, texture->baseTexture.level_count);
return WINED3DERR_INVALIDCALL;
}
return hr;
return IWineD3DVolume_LockBox((IWineD3DVolume *)texture->baseTexture.sub_resources[level], locked_box, box, flags);
}
static HRESULT WINAPI IWineD3DVolumeTextureImpl_UnlockBox(IWineD3DVolumeTexture *iface, UINT Level) {
HRESULT hr;
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
static HRESULT WINAPI IWineD3DVolumeTextureImpl_UnlockBox(IWineD3DVolumeTexture *iface, UINT level)
{
IWineD3DVolumeTextureImpl *texture = (IWineD3DVolumeTextureImpl *)iface;
if (Level < This->baseTexture.levels) {
hr = IWineD3DVolume_UnlockBox(This->volumes[Level]);
TRACE("(%p) -> level(%d) success(%u)\n", This, Level, hr);
TRACE("iface %p, level %u.\n", iface, level);
} else {
FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
if (level >= texture->baseTexture.level_count)
{
WARN("level %u >= level_count %u.\n", level, texture->baseTexture.level_count);
return WINED3DERR_INVALIDCALL;
}
return hr;
return IWineD3DVolume_UnlockBox((IWineD3DVolume *)texture->baseTexture.sub_resources[level]);
}
static HRESULT WINAPI IWineD3DVolumeTextureImpl_AddDirtyBox(IWineD3DVolumeTexture *iface, CONST WINED3DBOX* pDirtyBox) {
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
This->baseTexture.texture_rgb.dirty = TRUE;
This->baseTexture.texture_srgb.dirty = TRUE;
TRACE("(%p) : dirtyfication of volume Level (0)\n", This);
volume_add_dirty_box(This->volumes[0], pDirtyBox);
static HRESULT WINAPI IWineD3DVolumeTextureImpl_AddDirtyBox(IWineD3DVolumeTexture *iface, const WINED3DBOX *dirty_box)
{
IWineD3DVolumeTextureImpl *texture = (IWineD3DVolumeTextureImpl *)iface;
TRACE("iface %p, dirty_box %p.\n", iface, dirty_box);
texture->baseTexture.texture_rgb.dirty = TRUE;
texture->baseTexture.texture_srgb.dirty = TRUE;
volume_add_dirty_box((IWineD3DVolume *)texture->baseTexture.sub_resources[0], dirty_box);
return WINED3D_OK;
}
......@@ -399,8 +422,8 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT
texture->lpVtbl = &IWineD3DVolumeTexture_Vtbl;
hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_VOLUMETEXTURE,
device, 0, usage, format_desc, pool, parent, parent_ops);
hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, 1, levels,
WINED3DRTYPE_VOLUMETEXTURE, device, 0, usage, format_desc, pool, parent, parent_ops);
if (FAILED(hr))
{
WARN("Failed to initialize basetexture, returning %#x.\n", hr);
......@@ -418,21 +441,23 @@ HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT
tmp_h = height;
tmp_d = depth;
for (i = 0; i < texture->baseTexture.levels; ++i)
for (i = 0; i < texture->baseTexture.level_count; ++i)
{
IWineD3DVolume *volume;
/* Create the volume. */
hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent,
tmp_w, tmp_h, tmp_d, format, pool, usage, &texture->volumes[i]);
tmp_w, tmp_h, tmp_d, format, pool, usage, &volume);
if (FAILED(hr))
{
ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
texture->volumes[i] = NULL;
volumetexture_cleanup(texture);
return hr;
}
/* Set its container to this texture. */
IWineD3DVolume_SetContainer(texture->volumes[i], (IWineD3DBase *)texture);
IWineD3DVolume_SetContainer(volume, (IWineD3DBase *)texture);
texture->baseTexture.sub_resources[i] = (IWineD3DResourceImpl *)volume;
/* Calculate the next mipmap level. */
tmp_w = max(1, tmp_w >> 1);
......
......@@ -1860,7 +1860,9 @@ struct gl_texture
typedef struct IWineD3DBaseTextureClass
{
struct gl_texture texture_rgb, texture_srgb;
UINT levels;
IWineD3DResourceImpl **sub_resources;
UINT layer_count;
UINT level_count;
float pow2Matrix[16];
UINT LOD;
WINED3DTEXTUREFILTERTYPE filterType;
......@@ -1899,9 +1901,10 @@ WINED3DTEXTUREFILTERTYPE basetexture_get_autogen_filter_type(IWineD3DBaseTexture
BOOL basetexture_get_dirty(IWineD3DBaseTexture *iface) DECLSPEC_HIDDEN;
DWORD basetexture_get_level_count(IWineD3DBaseTexture *iface) DECLSPEC_HIDDEN;
DWORD basetexture_get_lod(IWineD3DBaseTexture *iface) DECLSPEC_HIDDEN;
HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT levels, WINED3DRESOURCETYPE resource_type,
IWineD3DDeviceImpl *device, UINT size, DWORD usage, const struct wined3d_format_desc *format_desc,
WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
HRESULT basetexture_init(IWineD3DBaseTextureImpl *texture, UINT layer_count, UINT level_count,
WINED3DRESOURCETYPE resource_type, IWineD3DDeviceImpl *device, UINT size, DWORD usage,
const struct wined3d_format_desc *format_desc, WINED3DPOOL pool, IUnknown *parent,
const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface,
WINED3DTEXTUREFILTERTYPE filter_type) DECLSPEC_HIDDEN;
BOOL basetexture_set_dirty(IWineD3DBaseTexture *iface, BOOL dirty) DECLSPEC_HIDDEN;
......@@ -1919,7 +1922,6 @@ typedef struct IWineD3DTextureImpl
IWineD3DBaseTextureClass baseTexture;
/* IWineD3DTexture */
IWineD3DSurface *surfaces[MAX_MIP_LEVELS];
UINT target;
BOOL cond_np2;
......@@ -1938,9 +1940,6 @@ typedef struct IWineD3DCubeTextureImpl
const IWineD3DCubeTextureVtbl *lpVtbl;
IWineD3DResourceClass resource;
IWineD3DBaseTextureClass baseTexture;
/* IWineD3DCubeTexture */
IWineD3DSurface *surfaces[6][MAX_MIP_LEVELS];
} IWineD3DCubeTextureImpl;
HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels,
......@@ -1987,9 +1986,6 @@ typedef struct IWineD3DVolumeTextureImpl
const IWineD3DVolumeTextureVtbl *lpVtbl;
IWineD3DResourceClass resource;
IWineD3DBaseTextureClass baseTexture;
/* IWineD3DVolumeTexture */
IWineD3DVolume *volumes[MAX_MIP_LEVELS];
} IWineD3DVolumeTextureImpl;
HRESULT volumetexture_init(IWineD3DVolumeTextureImpl *texture, UINT width, UINT height,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment