mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 04:10:09 +01:00
st/nine: Rework texture data allocation
Some applications assume the memory for multilevel textures is allocated per continuous blocks. This patch implements that behaviour. v2: cache offsets Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu> Signed-off-by: Axel Davy <axel.davy@ens.fr>
This commit is contained in:
parent
54f8e8a18d
commit
35fe920e1e
7 changed files with 130 additions and 36 deletions
|
|
@ -20,6 +20,8 @@
|
|||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "c99_alloca.h"
|
||||
|
||||
#include "device9.h"
|
||||
#include "cubetexture9.h"
|
||||
#include "nine_helpers.h"
|
||||
|
|
@ -40,8 +42,10 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
|
|||
struct pipe_resource *info = &This->base.base.info;
|
||||
struct pipe_screen *screen = pParams->device->screen;
|
||||
enum pipe_format pf;
|
||||
unsigned i;
|
||||
unsigned i, l, f, offset, face_size = 0;
|
||||
unsigned *level_offsets;
|
||||
D3DSURFACE_DESC sfdesc;
|
||||
void *p;
|
||||
HRESULT hr;
|
||||
|
||||
DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d "
|
||||
|
|
@ -97,6 +101,16 @@ 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 = MALLOC(6 * face_size);
|
||||
if (!This->managed_buffer)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces));
|
||||
if (!This->surfaces)
|
||||
return E_OUTOFMEMORY;
|
||||
|
|
@ -117,16 +131,25 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
|
|||
sfdesc.Pool = Pool;
|
||||
sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
sfdesc.MultiSampleQuality = 0;
|
||||
for (i = 0; i < (info->last_level + 1) * 6; ++i) {
|
||||
sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, i / 6);
|
||||
/* We allocate the memory for the surfaces as continous blocks.
|
||||
* This is the expected behaviour, however we haven't tested for
|
||||
* cube textures in which order the faces/levels should be in memory
|
||||
*/
|
||||
for (f = 0; f < 6; f++) {
|
||||
offset = f * face_size;
|
||||
for (l = 0; l <= info->last_level; l++) {
|
||||
sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l);
|
||||
p = This->managed_buffer ? This->managed_buffer + offset +
|
||||
level_offsets[l] : NULL;
|
||||
|
||||
hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
|
||||
This->base.base.resource, NULL, D3DRTYPE_CUBETEXTURE,
|
||||
i / 6, i % 6,
|
||||
&sfdesc, &This->surfaces[i]);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
|
||||
This->base.base.resource, p, D3DRTYPE_CUBETEXTURE,
|
||||
l, f, &sfdesc, &This->surfaces[f + 6 * l]);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
|
||||
This->dirty_rect[i].depth = 1;
|
||||
|
||||
|
|
@ -146,6 +169,9 @@ NineCubeTexture9_dtor( struct NineCubeTexture9 *This )
|
|||
FREE(This->surfaces);
|
||||
}
|
||||
|
||||
if (This->managed_buffer)
|
||||
FREE(This->managed_buffer);
|
||||
|
||||
NineBaseTexture9_dtor(&This->base);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct NineCubeTexture9
|
|||
struct NineBaseTexture9 base;
|
||||
struct NineSurface9 **surfaces;
|
||||
struct pipe_box dirty_rect[6]; /* covers all mip levels */
|
||||
uint8_t *managed_buffer;
|
||||
};
|
||||
static INLINE struct NineCubeTexture9 *
|
||||
NineCubeTexture9( void *data )
|
||||
|
|
|
|||
|
|
@ -673,4 +673,45 @@ d3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter)
|
|||
}
|
||||
}
|
||||
|
||||
static INLINE unsigned nine_format_get_stride(enum pipe_format format,
|
||||
unsigned width)
|
||||
{
|
||||
unsigned stride = util_format_get_stride(format, width);
|
||||
|
||||
return align(stride, 4);
|
||||
}
|
||||
|
||||
static INLINE unsigned nine_format_get_level_alloc_size(enum pipe_format format,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
unsigned level)
|
||||
{
|
||||
unsigned w, h, size;
|
||||
|
||||
w = u_minify(width, level);
|
||||
h = u_minify(height, level);
|
||||
size = nine_format_get_stride(format, w) *
|
||||
util_format_get_nblocksy(format, h);
|
||||
return size;
|
||||
}
|
||||
|
||||
static INLINE unsigned nine_format_get_size_and_offsets(enum pipe_format format,
|
||||
unsigned *offsets,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
unsigned last_level)
|
||||
{
|
||||
unsigned l, w, h, size = 0;
|
||||
|
||||
for (l = 0; l <= last_level; ++l) {
|
||||
w = u_minify(width, l);
|
||||
h = u_minify(height, l);
|
||||
offsets[l] = size;
|
||||
size += nine_format_get_stride(format, w) *
|
||||
util_format_get_nblocksy(format, h);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif /* _NINE_PIPE_H_ */
|
||||
|
|
|
|||
|
|
@ -62,10 +62,17 @@ NineSurface9_ctor( struct NineSurface9 *This,
|
|||
user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) ||
|
||||
(pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL);
|
||||
|
||||
assert(pResource ||
|
||||
pDesc->Pool != D3DPOOL_DEFAULT || pDesc->Format == D3DFMT_NULL);
|
||||
assert(pResource || (user_buffer && pDesc->Pool != D3DPOOL_DEFAULT) ||
|
||||
(!pContainer && pDesc->Pool != D3DPOOL_DEFAULT) ||
|
||||
pDesc->Format == D3DFMT_NULL);
|
||||
|
||||
assert(!pResource || !user_buffer);
|
||||
assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT);
|
||||
/* The only way we can have !pContainer is being created
|
||||
* from create_zs_or_rt_surface with params 0 0 0 */
|
||||
assert(pContainer || (Level == 0 && Layer == 0 && TextureType == 0));
|
||||
|
||||
This->data = (uint8_t *)user_buffer;
|
||||
|
||||
This->base.info.screen = pParams->device->screen;
|
||||
This->base.info.target = PIPE_TEXTURE_2D;
|
||||
|
|
@ -90,9 +97,20 @@ NineSurface9_ctor( struct NineSurface9 *This,
|
|||
if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL)
|
||||
This->base.info.bind |= PIPE_BIND_DEPTH_STENCIL;
|
||||
|
||||
/* Ram buffer with no parent. Has to allocate the resource itself */
|
||||
if (!pResource && !pContainer) {
|
||||
assert(!user_buffer);
|
||||
This->data = MALLOC(
|
||||
nine_format_get_level_alloc_size(This->base.info.format,
|
||||
pDesc->Width,
|
||||
pDesc->Height,
|
||||
0));
|
||||
if (!This->data)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if (pDesc->Pool == D3DPOOL_SYSTEMMEM) {
|
||||
This->base.info.usage = PIPE_USAGE_STAGING;
|
||||
This->data = (uint8_t *)user_buffer; /* this is *pSharedHandle */
|
||||
assert(!pResource);
|
||||
} else {
|
||||
if (pResource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
|
||||
|
|
@ -113,24 +131,10 @@ NineSurface9_ctor( struct NineSurface9 *This,
|
|||
This->layer = Layer;
|
||||
This->desc = *pDesc;
|
||||
|
||||
This->stride = util_format_get_stride(This->base.info.format, pDesc->Width);
|
||||
This->stride = align(This->stride, 4);
|
||||
This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width);
|
||||
|
||||
if (!pResource && !This->data) {
|
||||
const unsigned size = This->stride *
|
||||
util_format_get_nblocksy(This->base.info.format, This->desc.Height);
|
||||
|
||||
DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
|
||||
This->base.base.container, This, This->level, size);
|
||||
|
||||
This->data = (uint8_t *)MALLOC(size);
|
||||
if (!This->data)
|
||||
return E_OUTOFMEMORY;
|
||||
This->manage_data = TRUE;
|
||||
} else {
|
||||
if (pResource && NineSurface9_IsOffscreenPlain(This))
|
||||
pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; /* why setting this flag there ? too late ? should be before NineResource9_ctor call perhaps ? */
|
||||
}
|
||||
if (pResource && NineSurface9_IsOffscreenPlain(This))
|
||||
pResource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
|
||||
|
||||
NineSurface9_Dump(This);
|
||||
|
||||
|
|
@ -147,8 +151,8 @@ NineSurface9_dtor( struct NineSurface9 *This )
|
|||
pipe_surface_reference(&This->surface[0], NULL);
|
||||
pipe_surface_reference(&This->surface[1], NULL);
|
||||
|
||||
/* release allocated system memory for non-D3DPOOL_DEFAULT resources */
|
||||
if (This->manage_data && This->data)
|
||||
/* Release system memory when we have to manage it (no parent) */
|
||||
if (!This->base.base.container && This->data)
|
||||
FREE(This->data);
|
||||
NineResource9_dtor(&This->base);
|
||||
}
|
||||
|
|
@ -678,9 +682,8 @@ NineSurface9_SetResourceResize( struct NineSurface9 *This,
|
|||
This->desc.Height = This->base.info.height0 = resource->height0;
|
||||
This->desc.MultiSampleType = This->base.info.nr_samples = resource->nr_samples;
|
||||
|
||||
This->stride = util_format_get_stride(This->base.info.format,
|
||||
This->stride = nine_format_get_stride(This->base.info.format,
|
||||
This->desc.Width);
|
||||
This->stride = align(This->stride, 4);
|
||||
|
||||
pipe_surface_reference(&This->surface[0], NULL);
|
||||
pipe_surface_reference(&This->surface[1], NULL);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ struct NineSurface9
|
|||
D3DSURFACE_DESC desc;
|
||||
|
||||
uint8_t *data; /* system memory backing */
|
||||
boolean manage_data;
|
||||
unsigned stride; /* for system memory backing */
|
||||
|
||||
/* wine doesn't even use these, 2 will be enough */
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "c99_alloca.h"
|
||||
|
||||
#include "device9.h"
|
||||
#include "surface9.h"
|
||||
#include "texture9.h"
|
||||
|
|
@ -48,10 +50,11 @@ NineTexture9_ctor( struct NineTexture9 *This,
|
|||
struct pipe_resource *info = &This->base.base.info;
|
||||
struct pipe_resource *resource;
|
||||
enum pipe_format pf;
|
||||
unsigned *level_offsets;
|
||||
unsigned l;
|
||||
D3DSURFACE_DESC sfdesc;
|
||||
HRESULT hr;
|
||||
void *user_buffer = NULL;
|
||||
void *user_buffer = NULL, *user_buffer_for_level;
|
||||
|
||||
DBG("(%p) Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
|
||||
"pSharedHandle=%p\n", This, Width, Height, Levels,
|
||||
|
|
@ -138,6 +141,19 @@ NineTexture9_ctor( struct NineTexture9 *This,
|
|||
|
||||
if (pSharedHandle && *pSharedHandle) { /* Pool == D3DPOOL_SYSTEMMEM */
|
||||
user_buffer = (void *)*pSharedHandle;
|
||||
level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
|
||||
(void) nine_format_get_size_and_offsets(pf, level_offsets,
|
||||
Width, Height,
|
||||
info->last_level);
|
||||
} else if (Pool != D3DPOOL_DEFAULT) {
|
||||
level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
|
||||
user_buffer = MALLOC(
|
||||
nine_format_get_size_and_offsets(pf, level_offsets,
|
||||
Width, Height,
|
||||
info->last_level));
|
||||
This->managed_buffer = user_buffer;
|
||||
if (!This->managed_buffer)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces));
|
||||
|
|
@ -168,9 +184,13 @@ NineTexture9_ctor( struct NineTexture9 *This,
|
|||
for (l = 0; l <= info->last_level; ++l) {
|
||||
sfdesc.Width = u_minify(Width, l);
|
||||
sfdesc.Height = u_minify(Height, l);
|
||||
/* Some apps expect the memory to be allocated in
|
||||
* continous blocks */
|
||||
user_buffer_for_level = user_buffer ? user_buffer +
|
||||
level_offsets[l] : NULL;
|
||||
|
||||
hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
|
||||
resource, user_buffer,
|
||||
resource, user_buffer_for_level,
|
||||
D3DRTYPE_TEXTURE, l, 0,
|
||||
&sfdesc, &This->surfaces[l]);
|
||||
if (FAILED(hr))
|
||||
|
|
@ -198,6 +218,9 @@ NineTexture9_dtor( struct NineTexture9 *This )
|
|||
FREE(This->surfaces);
|
||||
}
|
||||
|
||||
if (This->managed_buffer)
|
||||
FREE(This->managed_buffer);
|
||||
|
||||
NineBaseTexture9_dtor(&This->base);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct NineTexture9
|
|||
struct NineBaseTexture9 base;
|
||||
struct NineSurface9 **surfaces;
|
||||
struct pipe_box dirty_rect; /* covers all mip levels */
|
||||
uint8_t *managed_buffer;
|
||||
};
|
||||
static INLINE struct NineTexture9 *
|
||||
NineTexture9( void *data )
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue