mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-03 02:10:24 +01:00
dri/nouveau: Try to validate textures earlier.
This commit is contained in:
parent
44602bb23c
commit
323e6bbb05
6 changed files with 189 additions and 110 deletions
|
|
@ -396,7 +396,6 @@ nouveau_tex_parameter(GLcontext *ctx, GLenum target,
|
|||
const GLfloat *params)
|
||||
{
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
|
|
@ -408,9 +407,10 @@ nouveau_tex_parameter(GLcontext *ctx, GLenum target,
|
|||
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
case GL_TEXTURE_BASE_LEVEL:
|
||||
case GL_TEXTURE_MAX_LEVEL:
|
||||
texture_dirty(t);
|
||||
nouveau_texture_reallocate(ctx, t);
|
||||
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,6 +171,148 @@ nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat,
|
|||
}
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
teximage_fits(struct gl_texture_object *t, int level,
|
||||
struct gl_texture_image *ti)
|
||||
{
|
||||
struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
|
||||
|
||||
return s->bo && s->width == ti->Width &&
|
||||
s->height == ti->Height &&
|
||||
s->format == ti->TexFormat;
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
validate_teximage(GLcontext *ctx, struct gl_texture_object *t,
|
||||
int level, int x, int y, int z,
|
||||
int width, int height, int depth)
|
||||
{
|
||||
struct gl_texture_image *ti = t->Image[0][level];
|
||||
|
||||
if (ti && teximage_fits(t, level, ti)) {
|
||||
struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
|
||||
struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
|
||||
|
||||
context_drv(ctx)->surface_copy(ctx, &ss[level], s,
|
||||
x, y, x, y,
|
||||
width, height);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
get_last_level(struct gl_texture_object *t)
|
||||
{
|
||||
struct gl_texture_image *base = t->Image[0][t->BaseLevel];
|
||||
|
||||
if (t->MinFilter == GL_NEAREST ||
|
||||
t->MinFilter == GL_LINEAR || !base)
|
||||
return t->BaseLevel;
|
||||
else
|
||||
return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel);
|
||||
}
|
||||
|
||||
static void
|
||||
relayout_texture(GLcontext *ctx, struct gl_texture_object *t)
|
||||
{
|
||||
struct gl_texture_image *base = t->Image[0][t->BaseLevel];
|
||||
|
||||
if (base) {
|
||||
struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
|
||||
struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
|
||||
int i, ret, last = get_last_level(t);
|
||||
unsigned size, offset = 0,
|
||||
width = s->width,
|
||||
height = s->height;
|
||||
|
||||
/* Deallocate the old storage. */
|
||||
for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
|
||||
nouveau_bo_ref(NULL, &ss[i].bo);
|
||||
|
||||
/* Relayout the mipmap tree. */
|
||||
for (i = t->BaseLevel; i <= last; i++) {
|
||||
size = width * height * s->cpp;
|
||||
|
||||
/* Images larger than 16B have to be aligned. */
|
||||
if (size > 16)
|
||||
offset = align(offset, 64);
|
||||
|
||||
ss[i] = (struct nouveau_surface) {
|
||||
.offset = offset,
|
||||
.layout = SWIZZLED,
|
||||
.format = s->format,
|
||||
.width = width,
|
||||
.height = height,
|
||||
.cpp = s->cpp,
|
||||
.pitch = width * s->cpp,
|
||||
};
|
||||
|
||||
offset += size;
|
||||
width = MAX2(1, width / 2);
|
||||
height = MAX2(1, height / 2);
|
||||
}
|
||||
|
||||
/* Get new storage. */
|
||||
size = align(offset, 64);
|
||||
|
||||
ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
|
||||
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
|
||||
0, size, &ss[last].bo);
|
||||
assert(!ret);
|
||||
|
||||
for (i = t->BaseLevel; i < last; i++)
|
||||
nouveau_bo_ref(ss[last].bo, &ss[i].bo);
|
||||
}
|
||||
}
|
||||
|
||||
GLboolean
|
||||
nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t)
|
||||
{
|
||||
struct nouveau_texture *nt = to_nouveau_texture(t);
|
||||
int i, last = get_last_level(t);
|
||||
|
||||
if (!nt->surfaces[last].bo)
|
||||
return GL_FALSE;
|
||||
|
||||
if (nt->dirty) {
|
||||
nt->dirty = GL_FALSE;
|
||||
|
||||
/* Copy the teximages to the actual miptree. */
|
||||
for (i = t->BaseLevel; i <= last; i++) {
|
||||
struct nouveau_surface *s = &nt->surfaces[i];
|
||||
|
||||
validate_teximage(ctx, t, i, 0, 0, 0,
|
||||
s->width, s->height, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t)
|
||||
{
|
||||
texture_dirty(t);
|
||||
relayout_texture(ctx, t);
|
||||
nouveau_texture_validate(ctx, t);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
get_teximage_placement(struct gl_texture_image *ti)
|
||||
{
|
||||
if (ti->TexFormat == MESA_FORMAT_A8 ||
|
||||
ti->TexFormat == MESA_FORMAT_L8 ||
|
||||
ti->TexFormat == MESA_FORMAT_I8)
|
||||
/* 1 cpp formats will have to be swizzled by the CPU,
|
||||
* so leave them in system RAM for now. */
|
||||
return NOUVEAU_BO_MAP;
|
||||
else
|
||||
return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
|
|
@ -181,37 +323,45 @@ nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
|
|||
struct gl_texture_image *ti)
|
||||
{
|
||||
struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
|
||||
unsigned bo_flags = NOUVEAU_BO_GART | NOUVEAU_BO_RDWR | NOUVEAU_BO_MAP;
|
||||
int ret;
|
||||
|
||||
/* Allocate a new bo for the image. */
|
||||
nouveau_surface_alloc(ctx, s, LINEAR, bo_flags, ti->TexFormat,
|
||||
width, height);
|
||||
nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
|
||||
ti->TexFormat, width, height);
|
||||
ti->RowStride = s->pitch / s->cpp;
|
||||
|
||||
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
|
||||
format, type, pixels, packing,
|
||||
"glTexImage");
|
||||
if (!pixels)
|
||||
return;
|
||||
if (pixels) {
|
||||
/* Store the pixel data. */
|
||||
nouveau_teximage_map(ctx, ti);
|
||||
|
||||
/* Store the pixel data. */
|
||||
nouveau_teximage_map(ctx, ti);
|
||||
ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
|
||||
ti->TexFormat, ti->Data,
|
||||
0, 0, 0, s->pitch,
|
||||
ti->ImageOffsets,
|
||||
width, height, depth,
|
||||
format, type, pixels, packing);
|
||||
assert(ret);
|
||||
|
||||
ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
|
||||
ti->TexFormat, ti->Data,
|
||||
0, 0, 0, s->pitch,
|
||||
ti->ImageOffsets,
|
||||
width, height, depth,
|
||||
format, type, pixels, packing);
|
||||
assert(ret);
|
||||
nouveau_teximage_unmap(ctx, ti);
|
||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||
|
||||
nouveau_teximage_unmap(ctx, ti);
|
||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||
if (!validate_teximage(ctx, t, level, 0, 0, 0,
|
||||
width, height, depth))
|
||||
/* It doesn't fit, mark it as dirty. */
|
||||
texture_dirty(t);
|
||||
}
|
||||
|
||||
if (level == t->BaseLevel) {
|
||||
if (!teximage_fits(t, level, ti))
|
||||
relayout_texture(ctx, t);
|
||||
nouveau_texture_validate(ctx, t);
|
||||
}
|
||||
|
||||
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
|
||||
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
|
||||
texture_dirty(t);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -271,8 +421,9 @@ nouveau_texsubimage_3d(GLcontext *ctx, GLenum target, GLint level,
|
|||
packing, t, ti);
|
||||
nouveau_teximage_unmap(ctx, ti);
|
||||
|
||||
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
|
||||
texture_dirty(t);
|
||||
if (!to_nouveau_texture(t)->dirty)
|
||||
validate_teximage(ctx, t, level, xoffset, yoffset, zoffset,
|
||||
width, height, depth);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -290,8 +441,9 @@ nouveau_texsubimage_2d(GLcontext *ctx, GLenum target, GLint level,
|
|||
packing, t, ti);
|
||||
nouveau_teximage_unmap(ctx, ti);
|
||||
|
||||
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
|
||||
texture_dirty(t);
|
||||
if (!to_nouveau_texture(t)->dirty)
|
||||
validate_teximage(ctx, t, level, xoffset, yoffset, 0,
|
||||
width, height, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -308,8 +460,9 @@ nouveau_texsubimage_1d(GLcontext *ctx, GLenum target, GLint level,
|
|||
packing, t, ti);
|
||||
nouveau_teximage_unmap(ctx, ti);
|
||||
|
||||
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
|
||||
texture_dirty(t);
|
||||
if (!to_nouveau_texture(t)->dirty)
|
||||
validate_teximage(ctx, t, level, xoffset, 0, 0,
|
||||
width, 1, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -354,87 +507,6 @@ nouveau_texture_unmap(GLcontext *ctx, struct gl_texture_object *t)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
relayout_miptree(GLcontext *ctx, struct gl_texture_object *t)
|
||||
{
|
||||
struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
|
||||
unsigned last_level, offset = 0;
|
||||
unsigned size;
|
||||
int i, ret;
|
||||
|
||||
if (t->MinFilter == GL_NEAREST ||
|
||||
t->MinFilter == GL_LINEAR)
|
||||
last_level = t->BaseLevel;
|
||||
else
|
||||
last_level = t->_MaxLevel;
|
||||
|
||||
/* Deallocate the old storage. */
|
||||
for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
|
||||
nouveau_bo_ref(NULL, &ss[i].bo);
|
||||
|
||||
/* Relayout the mipmap tree. */
|
||||
for (i = t->BaseLevel; i <= last_level; i++) {
|
||||
struct nouveau_surface *s =
|
||||
&to_nouveau_teximage(t->Image[0][i])->surface;
|
||||
|
||||
size = s->width * s->height * s->cpp;
|
||||
|
||||
/* Images larger than 16B have to be aligned. */
|
||||
if (size > 16)
|
||||
offset = align(offset, 64);
|
||||
|
||||
ss[i] = (struct nouveau_surface) {
|
||||
.offset = offset,
|
||||
.layout = SWIZZLED,
|
||||
.format = s->format,
|
||||
.width = s->width,
|
||||
.height = s->height,
|
||||
.cpp = s->cpp,
|
||||
.pitch = s->width * s->cpp,
|
||||
};
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
/* Get new storage. */
|
||||
size = align(offset, 64);
|
||||
|
||||
ret = nouveau_bo_new(context_dev(ctx),
|
||||
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
|
||||
0, size, &ss[last_level].bo);
|
||||
assert(!ret);
|
||||
|
||||
for (i = t->BaseLevel; i < last_level; i++)
|
||||
nouveau_bo_ref(ss[last_level].bo, &ss[i].bo);
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t)
|
||||
{
|
||||
struct nouveau_texture *nt = to_nouveau_texture(t);
|
||||
int i;
|
||||
|
||||
if (!nt->dirty)
|
||||
return;
|
||||
|
||||
nt->dirty = GL_FALSE;
|
||||
|
||||
relayout_miptree(ctx, t);
|
||||
|
||||
/* Copy the teximages to the actual swizzled miptree. */
|
||||
for (i = t->BaseLevel; i < MAX_TEXTURE_LEVELS; i++) {
|
||||
struct gl_texture_image *ti = t->Image[0][i];
|
||||
struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
|
||||
|
||||
if (!nt->surfaces[i].bo)
|
||||
break;
|
||||
|
||||
context_drv(ctx)->surface_copy(ctx, &nt->surfaces[i], s,
|
||||
0, 0, 0, 0,
|
||||
s->width, s->height);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_texture_functions_init(struct dd_function_table *functions)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ struct nouveau_texture {
|
|||
#define texture_dirty(t) \
|
||||
to_nouveau_texture(t)->dirty = GL_TRUE;
|
||||
|
||||
void
|
||||
GLboolean
|
||||
nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t);
|
||||
|
||||
void
|
||||
nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -89,7 +89,9 @@ nv04_emit_tex_obj(GLcontext *ctx, int emit)
|
|||
struct gl_texture_image *ti = t->Image[0][t->BaseLevel];
|
||||
int lod_max = 1, lod_bias = 0;
|
||||
|
||||
nouveau_texture_validate(ctx, t);
|
||||
if (!nouveau_texture_validate(ctx, t))
|
||||
return;
|
||||
|
||||
s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
|
||||
|
||||
if (t->MinFilter != GL_NEAREST &&
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ nv10_emit_tex_obj(GLcontext *ctx, int emit)
|
|||
s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
|
||||
ti = t->Image[0][t->BaseLevel];
|
||||
|
||||
nouveau_texture_validate(ctx, t);
|
||||
if (!nouveau_texture_validate(ctx, t))
|
||||
return;
|
||||
|
||||
/* Recompute the texturing registers. */
|
||||
tx_format = nvgl_wrap_mode(t->WrapT) << 28
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ nv20_emit_tex_obj(GLcontext *ctx, int emit)
|
|||
s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
|
||||
ti = t->Image[0][t->BaseLevel];
|
||||
|
||||
nouveau_texture_validate(ctx, t);
|
||||
if (!nouveau_texture_validate(ctx, t))
|
||||
return;
|
||||
|
||||
/* Recompute the texturing registers. */
|
||||
tx_format = ti->DepthLog2 << 28
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue