X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fnouveau%2Fnouveau_texture.c;h=dc5699c76809681c0f59c96515bfc034dc50b542;hb=da9e6fdfe27065b8ede8b2fe30c8cccc3b573245;hp=66c3cb25188c4f0c7f141424dc37b514f3bcc1ec;hpb=8b8a54afd9b748b7250993393864544ad6961edb;p=mesa.git diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c index 66c3cb25188..dc5699c7680 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.c @@ -46,7 +46,7 @@ nouveau_texture_new(struct gl_context *ctx, GLuint name, GLenum target) { struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture); - _mesa_initialize_texture_object(&nt->base, name, target); + _mesa_initialize_texture_object(ctx, &nt->base, name, target); return &nt->base; } @@ -79,72 +79,6 @@ nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti) nouveau_surface_ref(NULL, &nti->surface); } -static void -nouveau_teximage_map(struct gl_context *ctx, struct gl_texture_image *ti, - int access, int x, int y, int w, int h) -{ - struct nouveau_teximage *nti = to_nouveau_teximage(ti); - struct nouveau_surface *s = &nti->surface; - struct nouveau_surface *st = &nti->transfer.surface; - - if (s->bo) { - if (!(access & GL_MAP_READ_BIT) && - nouveau_bo_pending(s->bo)) { - /* - * Heuristic: use a bounce buffer to pipeline - * teximage transfers. - */ - st->layout = LINEAR; - st->format = s->format; - st->cpp = s->cpp; - st->width = w; - st->height = h; - st->pitch = s->pitch; - nti->transfer.x = x; - nti->transfer.y = y; - - nti->base.Map = nouveau_get_scratch(ctx, st->pitch * h, - &st->bo, &st->offset); - - } else { - int ret, flags = 0; - - if (access & GL_MAP_READ_BIT) - flags |= NOUVEAU_BO_RD; - if (access & GL_MAP_WRITE_BIT) - flags |= NOUVEAU_BO_WR; - - if (!s->bo->map) { - ret = nouveau_bo_map(s->bo, flags); - assert(!ret); - } - - nti->base.Map = s->bo->map + y * s->pitch + x * s->cpp; - } - } -} - -static void -nouveau_teximage_unmap(struct gl_context *ctx, struct gl_texture_image *ti) -{ - struct nouveau_teximage *nti = to_nouveau_teximage(ti); - struct nouveau_surface *s = &nti->surface; - struct nouveau_surface *st = &nti->transfer.surface; - - if (st->bo) { - context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x, - nti->transfer.y, 0, 0, - st->width, st->height); - nouveau_surface_ref(NULL, st); - - } else if (s->bo) { - nouveau_bo_unmap(s->bo); - } - - nti->base.Map = NULL; -} - - static void nouveau_map_texture_image(struct gl_context *ctx, struct gl_texture_image *ti, @@ -157,13 +91,15 @@ nouveau_map_texture_image(struct gl_context *ctx, struct nouveau_teximage *nti = to_nouveau_teximage(ti); struct nouveau_surface *s = &nti->surface; struct nouveau_surface *st = &nti->transfer.surface; + struct nouveau_client *client = context_client(ctx); /* Nouveau has no support for 3D or cubemap textures. */ assert(slice == 0); if (s->bo) { if (!(mode & GL_MAP_READ_BIT) && - nouveau_bo_pending(s->bo)) { + nouveau_pushbuf_refd(context_push(ctx), s->bo)) { + unsigned size; /* * Heuristic: use a bounce buffer to pipeline * teximage transfers. @@ -177,8 +113,9 @@ nouveau_map_texture_image(struct gl_context *ctx, nti->transfer.x = x; nti->transfer.y = y; - *map = nouveau_get_scratch(ctx, st->pitch * h, - &st->bo, &st->offset); + size = get_format_blocksy(st->format, h) * st->pitch; + *map = nouveau_get_scratch(ctx, size, + &st->bo, &st->offset); *stride = st->pitch; } else { int ret, flags = 0; @@ -189,15 +126,19 @@ nouveau_map_texture_image(struct gl_context *ctx, flags |= NOUVEAU_BO_WR; if (!s->bo->map) { - ret = nouveau_bo_map(s->bo, flags); + ret = nouveau_bo_map(s->bo, flags, client); assert(!ret); } - *map = s->bo->map + y * s->pitch + x * s->cpp; + *map = s->bo->map + + get_format_blocksy(s->format, y) * s->pitch + + get_format_blocksx(s->format, x) * s->cpp; *stride = s->pitch; } } else { - *map = nti->base.Map + y * s->pitch + x * s->cpp; + *map = nti->base.Buffer + + get_format_blocksy(s->format, y) * s->pitch + + get_format_blocksx(s->format, x) * s->cpp; *stride = s->pitch; } } @@ -216,15 +157,12 @@ nouveau_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *ti, st->width, st->height); nouveau_surface_ref(NULL, st); - } else if (s->bo) { - nouveau_bo_unmap(s->bo); } - - nti->base.Map = NULL; } -static gl_format -nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat, +static mesa_format +nouveau_choose_tex_format(struct gl_context *ctx, GLenum target, + GLint internalFormat, GLenum srcFormat, GLenum srcType) { switch (internalFormat) { @@ -237,9 +175,9 @@ nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat, case GL_RGBA16: case GL_RGB10_A2: case GL_COMPRESSED_RGBA: - return MESA_FORMAT_ARGB8888; + return MESA_FORMAT_B8G8R8A8_UNORM; case GL_RGB5_A1: - return MESA_FORMAT_ARGB1555; + return MESA_FORMAT_B5G5R5A1_UNORM; case GL_RGB: case GL_RGB8: @@ -247,12 +185,12 @@ nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat, case GL_RGB12: case GL_RGB16: case GL_COMPRESSED_RGB: - return MESA_FORMAT_XRGB8888; + return MESA_FORMAT_B8G8R8X8_UNORM; case 3: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: - return MESA_FORMAT_RGB565; + return MESA_FORMAT_B5G6R5_UNORM; case 2: case GL_LUMINANCE_ALPHA: @@ -263,7 +201,7 @@ nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat, case GL_LUMINANCE16_ALPHA16: case GL_LUMINANCE8_ALPHA8: case GL_COMPRESSED_LUMINANCE_ALPHA: - return MESA_FORMAT_ARGB8888; + return MESA_FORMAT_B8G8R8A8_UNORM; case 1: case GL_LUMINANCE: @@ -272,7 +210,7 @@ nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat, case GL_LUMINANCE16: case GL_LUMINANCE8: case GL_COMPRESSED_LUMINANCE: - return MESA_FORMAT_L8; + return MESA_FORMAT_L_UNORM8; case GL_ALPHA: case GL_ALPHA4: @@ -280,14 +218,31 @@ nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat, case GL_ALPHA16: case GL_ALPHA8: case GL_COMPRESSED_ALPHA: - return MESA_FORMAT_A8; + return MESA_FORMAT_A_UNORM8; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY12: case GL_INTENSITY16: case GL_INTENSITY8: - return MESA_FORMAT_I8; + case GL_COMPRESSED_INTENSITY: + return MESA_FORMAT_I_UNORM8; + + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return MESA_FORMAT_RGB_DXT1; + + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return MESA_FORMAT_RGBA_DXT1; + + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + return MESA_FORMAT_RGBA_DXT3; + + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return MESA_FORMAT_RGBA_DXT5; default: assert(0); @@ -344,7 +299,7 @@ get_last_level(struct gl_texture_object *t) t->Sampler.MinFilter == GL_LINEAR || !base) return t->BaseLevel; else - return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel); + return MIN2(t->BaseLevel + base->MaxNumLevels - 1, t->MaxLevel); } static void @@ -356,7 +311,9 @@ relayout_texture(struct gl_context *ctx, struct gl_texture_object *t) 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, + enum nouveau_surface_layout layout = + (_mesa_is_format_compressed(s->format) ? LINEAR : SWIZZLED); + unsigned size, pitch, offset = 0, width = s->width, height = s->height; @@ -366,7 +323,8 @@ relayout_texture(struct gl_context *ctx, struct gl_texture_object *t) /* Relayout the mipmap tree. */ for (i = t->BaseLevel; i <= last; i++) { - size = width * height * s->cpp; + pitch = _mesa_format_row_stride(s->format, width); + size = get_format_blocksy(s->format, height) * pitch; /* Images larger than 16B have to be aligned. */ if (size > 16) @@ -374,29 +332,32 @@ relayout_texture(struct gl_context *ctx, struct gl_texture_object *t) ss[i] = (struct nouveau_surface) { .offset = offset, - .layout = SWIZZLED, + .layout = layout, .format = s->format, .width = width, .height = height, .cpp = s->cpp, - .pitch = width * s->cpp, + .pitch = pitch, }; offset += size; - width = MAX2(1, width / 2); - height = MAX2(1, height / 2); + width = minify(width, 1); + height = minify(height, 1); } - /* Get new storage. */ - size = align(offset, 64); + if (t->BaseLevel <= last) { + /* Get new storage. */ + size = align(offset, 64); + assert(size); - ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP | - NOUVEAU_BO_GART | NOUVEAU_BO_VRAM, - 0, size, &ss[last].bo); - assert(!ret); + ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP | + NOUVEAU_BO_GART | NOUVEAU_BO_VRAM, + 0, size, NULL, &ss[last].bo); + assert(!ret); - for (i = t->BaseLevel; i < last; i++) - nouveau_bo_ref(ss[last].bo, &ss[i].bo); + for (i = t->BaseLevel; i < last; i++) + nouveau_bo_ref(ss[last].bo, &ss[i].bo); + } } } @@ -421,7 +382,7 @@ nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t) s->width, s->height, 1); } - FIRE_RING(context_chan(ctx)); + PUSH_KICK(context_push(ctx)); } return GL_TRUE; @@ -441,9 +402,9 @@ nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *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) + if (ti->TexFormat == MESA_FORMAT_A_UNORM8 || + ti->TexFormat == MESA_FORMAT_L_UNORM8 || + ti->TexFormat == MESA_FORMAT_I_UNORM8) /* 1 cpp formats will have to be swizzled by the CPU, * so leave them in system RAM for now. */ return NOUVEAU_BO_MAP; @@ -451,46 +412,89 @@ get_teximage_placement(struct gl_texture_image *ti) return NOUVEAU_BO_GART | NOUVEAU_BO_MAP; } +static void +nouveau_compressed_copy(struct gl_context *ctx, GLint dims, + struct gl_texture_image *ti, + GLsizei width, GLsizei height, GLsizei depth, + const GLvoid *src, GLvoid *dst, int row_stride) +{ + struct compressed_pixelstore store; + int i; + + _mesa_compute_compressed_pixelstore(dims, ti->TexFormat, + width, height, depth, + &ctx->Unpack, &store); + + src += store.SkipBytes; + + assert(store.CopySlices == 1); + + /* copy rows of blocks */ + for (i = 0; i < store.CopyRowsPerSlice; i++) { + memcpy(dst, src, store.CopyBytesPerRow); + dst += row_stride; + src += store.TotalBytesPerRow; + } +} + static void nouveau_teximage(struct gl_context *ctx, GLint dims, struct gl_texture_image *ti, - GLint internalFormat, - GLint width, GLint height, GLint depth, GLint border, + GLsizei imageSize, GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing) + const struct gl_pixelstore_attrib *packing, + GLboolean compressed) { struct gl_texture_object *t = ti->TexObject; const GLuint level = ti->Level; struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; struct nouveau_teximage *nti = to_nouveau_teximage(ti); int ret; + GLuint depth = compressed ? 1 : ti->Depth; /* Allocate a new bo for the image. */ nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti), - ti->TexFormat, width, height); + ti->TexFormat, ti->Width, ti->Height); nti->base.RowStride = s->pitch / s->cpp; - pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, - format, type, pixels, packing, - "glTexImage"); + if (compressed) + pixels = _mesa_validate_pbo_compressed_teximage(ctx, + dims, imageSize, + pixels, packing, "glCompressedTexImage"); + else + pixels = _mesa_validate_pbo_teximage(ctx, + dims, ti->Width, ti->Height, depth, format, type, + pixels, packing, "glTexImage"); + if (pixels) { + GLubyte *map; + int row_stride; + /* Store the pixel data. */ - nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT, - 0, 0, width, height); - - ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, - ti->TexFormat, - s->pitch, - &nti->base.Map, - width, height, depth, - format, type, pixels, packing); - assert(ret); - - nouveau_teximage_unmap(ctx, ti); + nouveau_map_texture_image(ctx, ti, 0, + 0, 0, ti->Width, ti->Height, + GL_MAP_WRITE_BIT, + &map, &row_stride); + + if (compressed) { + nouveau_compressed_copy(ctx, dims, ti, + ti->Width, ti->Height, depth, + pixels, map, row_stride); + } else { + ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, + ti->TexFormat, + row_stride, + &map, + ti->Width, ti->Height, depth, + format, type, pixels, packing); + assert(ret); + } + + nouveau_unmap_texture_image(ctx, ti, 0); _mesa_unmap_teximage_pbo(ctx, packing); if (!validate_teximage(ctx, t, level, 0, 0, 0, - width, height, depth)) + ti->Width, ti->Height, depth)) /* It doesn't fit, mark it as dirty. */ texture_dirty(t); } @@ -505,43 +509,33 @@ nouveau_teximage(struct gl_context *ctx, GLint dims, context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); } + static void -nouveau_teximage_1d(struct gl_context *ctx, - struct gl_texture_image *ti, - GLint internalFormat, - GLint width, GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing) +nouveau_teximage_123d(struct gl_context *ctx, GLuint dims, + struct gl_texture_image *ti, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing) { - nouveau_teximage(ctx, 1, ti, internalFormat, - width, 1, 1, border, format, type, pixels, - packing); + nouveau_teximage(ctx, dims, ti, 0, format, type, pixels, + packing, GL_FALSE); } static void -nouveau_teximage_2d(struct gl_context *ctx, +nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *ti, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing) + GLsizei imageSize, const GLvoid *data) { - nouveau_teximage(ctx, 2, ti, internalFormat, - width, height, 1, border, format, type, pixels, - packing); + nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data, + &ctx->Unpack, GL_TRUE); } -static void -nouveau_teximage_3d(struct gl_context *ctx, - struct gl_texture_image *ti, - GLint internalFormat, - GLint width, GLint height, GLint depth, GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing) +static GLboolean +nouveau_teximage_alloc(struct gl_context *ctx, struct gl_texture_image *ti) { - nouveau_teximage(ctx, 3, ti, internalFormat, - width, height, depth, border, format, type, pixels, - packing); + nouveau_teximage(ctx, 3, ti, 0, 0, 0, NULL, + &ctx->DefaultPacking, + _mesa_is_format_compressed(ti->TexFormat)); + return GL_TRUE; } static void @@ -549,28 +543,44 @@ nouveau_texsubimage(struct gl_context *ctx, GLint dims, struct gl_texture_image *ti, GLint xoffset, GLint yoffset, GLint zoffset, GLint width, GLint height, GLint depth, + GLsizei imageSize, GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing) + const struct gl_pixelstore_attrib *packing, + GLboolean compressed) { - struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; - struct nouveau_teximage *nti = to_nouveau_teximage(ti); int ret; - pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, - format, type, pixels, packing, - "glTexSubImage"); + if (compressed) + pixels = _mesa_validate_pbo_compressed_teximage(ctx, + dims, imageSize, + pixels, packing, "glCompressedTexSubImage"); + else + pixels = _mesa_validate_pbo_teximage(ctx, + dims, width, height, depth, format, type, + pixels, packing, "glTexSubImage"); + if (pixels) { - nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT, - xoffset, yoffset, width, height); + GLubyte *map; + int row_stride; + + nouveau_map_texture_image(ctx, ti, 0, + xoffset, yoffset, width, height, + GL_MAP_WRITE_BIT, &map, &row_stride); - ret = _mesa_texstore(ctx, 3, ti->_BaseFormat, ti->TexFormat, - s->pitch, - &nti->base.Map, - width, height, depth, - format, type, pixels, packing); - assert(ret); + if (compressed) { + nouveau_compressed_copy(ctx, dims, ti, + width, height, depth, + pixels, map, row_stride); + } else { + ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, + ti->TexFormat, + row_stride, &map, + width, height, depth, + format, type, pixels, packing); + assert(ret); + } - nouveau_teximage_unmap(ctx, ti); + nouveau_unmap_texture_image(ctx, ti, 0); _mesa_unmap_teximage_pbo(ctx, packing); } @@ -581,52 +591,40 @@ nouveau_texsubimage(struct gl_context *ctx, GLint dims, } static void -nouveau_texsubimage_3d(struct gl_context *ctx, - struct gl_texture_image *ti, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing) -{ - nouveau_texsubimage(ctx, 3, ti, xoffset, yoffset, zoffset, - width, height, depth, format, type, pixels, - packing); -} - -static void -nouveau_texsubimage_2d(struct gl_context *ctx, - struct gl_texture_image *ti, - GLint xoffset, GLint yoffset, - GLint width, GLint height, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing) +nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims, + struct gl_texture_image *ti, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing) { - nouveau_texsubimage(ctx, 2, ti, xoffset, yoffset, 0, - width, height, 1, format, type, pixels, - packing); + nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset, + width, height, depth, 0, format, type, pixels, + packing, GL_FALSE); } static void -nouveau_texsubimage_1d(struct gl_context *ctx, +nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *ti, - GLint xoffset, GLint width, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing) + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLint height, GLint depth, + GLenum format, + GLint imageSize, const void *data) { - nouveau_texsubimage(ctx, 1, ti, xoffset, 0, 0, - width, 1, 1, format, type, pixels, - packing); + nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset, + width, height, depth, imageSize, format, 0, data, + &ctx->Unpack, GL_TRUE); } static void -nouveau_bind_texture(struct gl_context *ctx, GLenum target, - struct gl_texture_object *t) +nouveau_bind_texture(struct gl_context *ctx, GLuint texUnit, + GLenum target, struct gl_texture_object *t) { - context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); - context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); + context_dirty_i(ctx, TEX_OBJ, texUnit); + context_dirty_i(ctx, TEX_ENV, texUnit); } -static gl_format +static mesa_format get_texbuffer_format(struct gl_renderbuffer *rb, GLint format) { struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; @@ -634,9 +632,9 @@ get_texbuffer_format(struct gl_renderbuffer *rb, GLint format) if (s->cpp < 4) return s->format; else if (format == __DRI_TEXTURE_FORMAT_RGBA) - return MESA_FORMAT_ARGB8888; + return MESA_FORMAT_B8G8R8A8_UNORM; else - return MESA_FORMAT_XRGB8888; + return MESA_FORMAT_B8G8R8X8_UNORM; } void @@ -687,13 +685,12 @@ nouveau_texture_functions_init(struct dd_function_table *functions) functions->DeleteTexture = nouveau_texture_free; functions->NewTextureImage = nouveau_teximage_new; functions->FreeTextureImageBuffer = nouveau_teximage_free; + functions->AllocTextureImageBuffer = nouveau_teximage_alloc; functions->ChooseTextureFormat = nouveau_choose_tex_format; - functions->TexImage1D = nouveau_teximage_1d; - functions->TexImage2D = nouveau_teximage_2d; - functions->TexImage3D = nouveau_teximage_3d; - functions->TexSubImage1D = nouveau_texsubimage_1d; - functions->TexSubImage2D = nouveau_texsubimage_2d; - functions->TexSubImage3D = nouveau_texsubimage_3d; + functions->TexImage = nouveau_teximage_123d; + functions->TexSubImage = nouveau_texsubimage_123d; + functions->CompressedTexImage = nouveau_compressed_teximage; + functions->CompressedTexSubImage = nouveau_compressed_texsubimage; functions->BindTexture = nouveau_bind_texture; functions->MapTextureImage = nouveau_map_texture_image; functions->UnmapTextureImage = nouveau_unmap_texture_image;