Home | History | Annotate | Download | only in nouveau
      1 /*
      2  * Copyright (C) 2009 Francisco Jerez.
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial
     15  * portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  */
     26 
     27 #include "nouveau_driver.h"
     28 #include "nouveau_context.h"
     29 #include "nouveau_texture.h"
     30 #include "nouveau_fbo.h"
     31 #include "nouveau_util.h"
     32 
     33 #include "main/pbo.h"
     34 #include "main/texobj.h"
     35 #include "main/texstore.h"
     36 #include "main/texformat.h"
     37 #include "main/texcompress.h"
     38 #include "main/texgetimage.h"
     39 #include "main/mipmap.h"
     40 #include "main/teximage.h"
     41 #include "drivers/common/meta.h"
     42 #include "swrast/s_texfetch.h"
     43 
     44 static struct gl_texture_object *
     45 nouveau_texture_new(struct gl_context *ctx, GLuint name, GLenum target)
     46 {
     47 	struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture);
     48 
     49 	_mesa_initialize_texture_object(&nt->base, name, target);
     50 
     51 	return &nt->base;
     52 }
     53 
     54 static void
     55 nouveau_texture_free(struct gl_context *ctx, struct gl_texture_object *t)
     56 {
     57 	struct nouveau_texture *nt = to_nouveau_texture(t);
     58 	int i;
     59 
     60 	for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
     61 		nouveau_surface_ref(NULL, &nt->surfaces[i]);
     62 
     63 	_mesa_delete_texture_object(ctx, t);
     64 }
     65 
     66 static struct gl_texture_image *
     67 nouveau_teximage_new(struct gl_context *ctx)
     68 {
     69 	struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
     70 
     71 	return &nti->base.Base;
     72 }
     73 
     74 static void
     75 nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti)
     76 {
     77 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
     78 
     79 	nouveau_surface_ref(NULL, &nti->surface);
     80 }
     81 
     82 static void
     83 nouveau_teximage_map(struct gl_context *ctx, struct gl_texture_image *ti,
     84 		     int access, int x, int y, int w, int h)
     85 {
     86 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
     87 	struct nouveau_surface *s = &nti->surface;
     88 	struct nouveau_surface *st = &nti->transfer.surface;
     89 	struct nouveau_client *client = context_client(ctx);
     90 
     91 	if (s->bo) {
     92 		if (!(access & GL_MAP_READ_BIT) &&
     93 		    nouveau_pushbuf_refd(context_push(ctx), s->bo)) {
     94 			unsigned size;
     95 			/*
     96 			 * Heuristic: use a bounce buffer to pipeline
     97 			 * teximage transfers.
     98 			 */
     99 			st->layout = LINEAR;
    100 			st->format = s->format;
    101 			st->cpp = s->cpp;
    102 			st->width = w;
    103 			st->height = h;
    104 			st->pitch = s->pitch;
    105 			nti->transfer.x = x;
    106 			nti->transfer.y = y;
    107 
    108 			size = get_format_blocksy(st->format, h) * st->pitch;
    109 			nti->base.Map = nouveau_get_scratch(ctx, size,
    110 						       &st->bo, &st->offset);
    111 
    112 		} else {
    113 			int ret, flags = 0;
    114 
    115 			if (access & GL_MAP_READ_BIT)
    116 				flags |= NOUVEAU_BO_RD;
    117 			if (access & GL_MAP_WRITE_BIT)
    118 				flags |= NOUVEAU_BO_WR;
    119 
    120 			if (!s->bo->map) {
    121 				ret = nouveau_bo_map(s->bo, flags, client);
    122 				assert(!ret);
    123 			}
    124 
    125 			nti->base.Map = s->bo->map +
    126 				get_format_blocksy(s->format, y) * s->pitch +
    127 				get_format_blocksx(s->format, x) * s->cpp;
    128 
    129 		}
    130 	}
    131 }
    132 
    133 static void
    134 nouveau_teximage_unmap(struct gl_context *ctx, struct gl_texture_image *ti)
    135 {
    136 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
    137 	struct nouveau_surface *s = &nti->surface;
    138 	struct nouveau_surface *st = &nti->transfer.surface;
    139 
    140 	if (st->bo) {
    141 		context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x,
    142 					       nti->transfer.y, 0, 0,
    143 					       st->width, st->height);
    144 		nouveau_surface_ref(NULL, st);
    145 
    146 	}
    147 	nti->base.Map = NULL;
    148 }
    149 
    150 
    151 static void
    152 nouveau_map_texture_image(struct gl_context *ctx,
    153 			  struct gl_texture_image *ti,
    154 			  GLuint slice,
    155 			  GLuint x, GLuint y, GLuint w, GLuint h,
    156 			  GLbitfield mode,
    157 			  GLubyte **map,
    158 			  GLint *stride)
    159 {
    160 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
    161 	struct nouveau_surface *s = &nti->surface;
    162 	struct nouveau_surface *st = &nti->transfer.surface;
    163 	struct nouveau_client *client = context_client(ctx);
    164 
    165 	/* Nouveau has no support for 3D or cubemap textures. */
    166 	assert(slice == 0);
    167 
    168 	if (s->bo) {
    169 		if (!(mode & GL_MAP_READ_BIT) &&
    170 		    nouveau_pushbuf_refd(context_push(ctx), s->bo)) {
    171 			unsigned size;
    172 			/*
    173 			 * Heuristic: use a bounce buffer to pipeline
    174 			 * teximage transfers.
    175 			 */
    176 			st->layout = LINEAR;
    177 			st->format = s->format;
    178 			st->cpp = s->cpp;
    179 			st->width = w;
    180 			st->height = h;
    181 			st->pitch = s->pitch;
    182 			nti->transfer.x = x;
    183 			nti->transfer.y = y;
    184 
    185 			size = get_format_blocksy(st->format, h) * st->pitch;
    186 			*map = nouveau_get_scratch(ctx, size,
    187 					  &st->bo, &st->offset);
    188 			*stride = st->pitch;
    189 		} else {
    190 			int ret, flags = 0;
    191 
    192 			if (mode & GL_MAP_READ_BIT)
    193 				flags |= NOUVEAU_BO_RD;
    194 			if (mode & GL_MAP_WRITE_BIT)
    195 				flags |= NOUVEAU_BO_WR;
    196 
    197 			if (!s->bo->map) {
    198 				ret = nouveau_bo_map(s->bo, flags, client);
    199 				assert(!ret);
    200 			}
    201 
    202 			*map = s->bo->map +
    203 				get_format_blocksy(s->format, y) * s->pitch +
    204 				get_format_blocksx(s->format, x) * s->cpp;
    205 			*stride = s->pitch;
    206 		}
    207 	} else {
    208 		*map = nti->base.Map +
    209 			get_format_blocksy(s->format, y) * s->pitch +
    210 			get_format_blocksx(s->format, x) * s->cpp;
    211 		*stride = s->pitch;
    212 	}
    213 }
    214 
    215 static void
    216 nouveau_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *ti,
    217 			    GLuint slice)
    218 {
    219 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
    220 	struct nouveau_surface *s = &nti->surface;
    221 	struct nouveau_surface *st = &nti->transfer.surface;
    222 
    223 	if (st->bo) {
    224 		context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x,
    225 					       nti->transfer.y, 0, 0,
    226 					       st->width, st->height);
    227 		nouveau_surface_ref(NULL, st);
    228 
    229 	}
    230 
    231 	nti->base.Map = NULL;
    232 }
    233 
    234 static gl_format
    235 nouveau_choose_tex_format(struct gl_context *ctx, GLenum target,
    236                           GLint internalFormat,
    237 			  GLenum srcFormat, GLenum srcType)
    238 {
    239 	switch (internalFormat) {
    240 	case 4:
    241 	case GL_RGBA:
    242 	case GL_RGBA2:
    243 	case GL_RGBA4:
    244 	case GL_RGBA8:
    245 	case GL_RGBA12:
    246 	case GL_RGBA16:
    247 	case GL_RGB10_A2:
    248 	case GL_COMPRESSED_RGBA:
    249 		return MESA_FORMAT_ARGB8888;
    250 	case GL_RGB5_A1:
    251 		return MESA_FORMAT_ARGB1555;
    252 
    253 	case GL_RGB:
    254 	case GL_RGB8:
    255 	case GL_RGB10:
    256 	case GL_RGB12:
    257 	case GL_RGB16:
    258 	case GL_COMPRESSED_RGB:
    259 		return MESA_FORMAT_XRGB8888;
    260 	case 3:
    261 	case GL_R3_G3_B2:
    262 	case GL_RGB4:
    263 	case GL_RGB5:
    264 		return MESA_FORMAT_RGB565;
    265 
    266 	case 2:
    267 	case GL_LUMINANCE_ALPHA:
    268 	case GL_LUMINANCE4_ALPHA4:
    269 	case GL_LUMINANCE6_ALPHA2:
    270 	case GL_LUMINANCE12_ALPHA4:
    271 	case GL_LUMINANCE12_ALPHA12:
    272 	case GL_LUMINANCE16_ALPHA16:
    273 	case GL_LUMINANCE8_ALPHA8:
    274 	case GL_COMPRESSED_LUMINANCE_ALPHA:
    275 		return MESA_FORMAT_ARGB8888;
    276 
    277 	case 1:
    278 	case GL_LUMINANCE:
    279 	case GL_LUMINANCE4:
    280 	case GL_LUMINANCE12:
    281 	case GL_LUMINANCE16:
    282 	case GL_LUMINANCE8:
    283 	case GL_COMPRESSED_LUMINANCE:
    284 		return MESA_FORMAT_L8;
    285 
    286 	case GL_ALPHA:
    287 	case GL_ALPHA4:
    288 	case GL_ALPHA12:
    289 	case GL_ALPHA16:
    290 	case GL_ALPHA8:
    291 	case GL_COMPRESSED_ALPHA:
    292 		return MESA_FORMAT_A8;
    293 
    294 	case GL_INTENSITY:
    295 	case GL_INTENSITY4:
    296 	case GL_INTENSITY12:
    297 	case GL_INTENSITY16:
    298 	case GL_INTENSITY8:
    299 		return MESA_FORMAT_I8;
    300 
    301 	case GL_RGB_S3TC:
    302 	case GL_RGB4_S3TC:
    303 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    304 		return MESA_FORMAT_RGB_DXT1;
    305 
    306 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    307 		return MESA_FORMAT_RGBA_DXT1;
    308 
    309 	case GL_RGBA_S3TC:
    310 	case GL_RGBA4_S3TC:
    311 	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    312 		return MESA_FORMAT_RGBA_DXT3;
    313 
    314 	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
    315 		return MESA_FORMAT_RGBA_DXT5;
    316 
    317 	default:
    318 		assert(0);
    319 	}
    320 }
    321 
    322 static GLboolean
    323 teximage_fits(struct gl_texture_object *t, int level)
    324 {
    325 	struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
    326 	struct gl_texture_image *ti = t->Image[0][level];
    327 
    328 	if (!ti || !to_nouveau_teximage(ti)->surface.bo)
    329 		return GL_FALSE;
    330 
    331 	if (level == t->BaseLevel && (s->offset & 0x7f))
    332 		return GL_FALSE;
    333 
    334 	return t->Target == GL_TEXTURE_RECTANGLE ||
    335 		(s->bo && s->format == ti->TexFormat &&
    336 		 s->width == ti->Width && s->height == ti->Height);
    337 }
    338 
    339 static GLboolean
    340 validate_teximage(struct gl_context *ctx, struct gl_texture_object *t,
    341 		  int level, int x, int y, int z,
    342 		  int width, int height, int depth)
    343 {
    344 	struct gl_texture_image *ti = t->Image[0][level];
    345 
    346 	if (teximage_fits(t, level)) {
    347 		struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
    348 		struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
    349 
    350 		if (t->Target == GL_TEXTURE_RECTANGLE)
    351 			nouveau_surface_ref(s, &ss[level]);
    352 		else
    353 			context_drv(ctx)->surface_copy(ctx, &ss[level], s,
    354 						       x, y, x, y,
    355 						       width, height);
    356 
    357 		return GL_TRUE;
    358 	}
    359 
    360 	return GL_FALSE;
    361 }
    362 
    363 static int
    364 get_last_level(struct gl_texture_object *t)
    365 {
    366 	struct gl_texture_image *base = t->Image[0][t->BaseLevel];
    367 
    368 	if (t->Sampler.MinFilter == GL_NEAREST ||
    369 	    t->Sampler.MinFilter == GL_LINEAR || !base)
    370 		return t->BaseLevel;
    371 	else
    372 		return MIN2(t->BaseLevel + base->MaxNumLevels - 1, t->MaxLevel);
    373 }
    374 
    375 static void
    376 relayout_texture(struct gl_context *ctx, struct gl_texture_object *t)
    377 {
    378 	struct gl_texture_image *base = t->Image[0][t->BaseLevel];
    379 
    380 	if (base && t->Target != GL_TEXTURE_RECTANGLE) {
    381 		struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
    382 		struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
    383 		int i, ret, last = get_last_level(t);
    384 		enum nouveau_surface_layout layout =
    385 			(_mesa_is_format_compressed(s->format) ? LINEAR : SWIZZLED);
    386 		unsigned size, pitch, offset = 0,
    387 			width = s->width,
    388 			height = s->height;
    389 
    390 		/* Deallocate the old storage. */
    391 		for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
    392 			nouveau_bo_ref(NULL, &ss[i].bo);
    393 
    394 		/* Relayout the mipmap tree. */
    395 		for (i = t->BaseLevel; i <= last; i++) {
    396 			pitch = _mesa_format_row_stride(s->format, width);
    397 			size = get_format_blocksy(s->format, height) * pitch;
    398 
    399 			/* Images larger than 16B have to be aligned. */
    400 			if (size > 16)
    401 				offset = align(offset, 64);
    402 
    403 			ss[i] = (struct nouveau_surface) {
    404 				.offset = offset,
    405 				.layout = layout,
    406 				.format = s->format,
    407 				.width = width,
    408 				.height = height,
    409 				.cpp = s->cpp,
    410 				.pitch = pitch,
    411 			};
    412 
    413 			offset += size;
    414 			width = MAX2(1, width / 2);
    415 			height = MAX2(1, height / 2);
    416 		}
    417 
    418 		/* Get new storage. */
    419 		size = align(offset, 64);
    420 
    421 		ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
    422 				     NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
    423 				     0, size, NULL, &ss[last].bo);
    424 		assert(!ret);
    425 
    426 		for (i = t->BaseLevel; i < last; i++)
    427 			nouveau_bo_ref(ss[last].bo, &ss[i].bo);
    428 	}
    429 }
    430 
    431 GLboolean
    432 nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t)
    433 {
    434 	struct nouveau_texture *nt = to_nouveau_texture(t);
    435 	int i, last = get_last_level(t);
    436 
    437 	if (!teximage_fits(t, t->BaseLevel) ||
    438 	    !teximage_fits(t, last))
    439 		return GL_FALSE;
    440 
    441 	if (nt->dirty) {
    442 		nt->dirty = GL_FALSE;
    443 
    444 		/* Copy the teximages to the actual miptree. */
    445 		for (i = t->BaseLevel; i <= last; i++) {
    446 			struct nouveau_surface *s = &nt->surfaces[i];
    447 
    448 			validate_teximage(ctx, t, i, 0, 0, 0,
    449 					  s->width, s->height, 1);
    450 		}
    451 
    452 		PUSH_KICK(context_push(ctx));
    453 	}
    454 
    455 	return GL_TRUE;
    456 }
    457 
    458 void
    459 nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t)
    460 {
    461 	if (!teximage_fits(t, t->BaseLevel) ||
    462 	    !teximage_fits(t, get_last_level(t))) {
    463 		texture_dirty(t);
    464 		relayout_texture(ctx, t);
    465 		nouveau_texture_validate(ctx, t);
    466 	}
    467 }
    468 
    469 static unsigned
    470 get_teximage_placement(struct gl_texture_image *ti)
    471 {
    472 	if (ti->TexFormat == MESA_FORMAT_A8 ||
    473 	    ti->TexFormat == MESA_FORMAT_L8 ||
    474 	    ti->TexFormat == MESA_FORMAT_I8)
    475 		/* 1 cpp formats will have to be swizzled by the CPU,
    476 		 * so leave them in system RAM for now. */
    477 		return NOUVEAU_BO_MAP;
    478 	else
    479 		return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
    480 }
    481 
    482 static void
    483 nouveau_teximage(struct gl_context *ctx, GLint dims,
    484 		 struct gl_texture_image *ti,
    485 		 GLsizei imageSize,
    486 		 GLenum format, GLenum type, const GLvoid *pixels,
    487 		 const struct gl_pixelstore_attrib *packing,
    488 		 GLboolean compressed)
    489 {
    490 	struct gl_texture_object *t = ti->TexObject;
    491 	const GLuint level = ti->Level;
    492 	struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
    493 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
    494 	int ret;
    495 	GLuint depth = compressed ? 1 : ti->Depth;
    496 
    497 	/* Allocate a new bo for the image. */
    498 	nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
    499 			      ti->TexFormat, ti->Width, ti->Height);
    500 	nti->base.RowStride = s->pitch / s->cpp;
    501 
    502 	if (compressed)
    503 		pixels = _mesa_validate_pbo_compressed_teximage(ctx,
    504 			imageSize,
    505 			pixels, packing, "glCompressedTexImage");
    506 	else
    507 		pixels = _mesa_validate_pbo_teximage(ctx,
    508 			dims, ti->Width, ti->Height, depth, format, type,
    509 			pixels, packing, "glTexImage");
    510 
    511 	if (pixels) {
    512 		/* Store the pixel data. */
    513 		nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
    514 				     0, 0, ti->Width, ti->Height);
    515 
    516 		ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
    517 				     ti->TexFormat,
    518 				     s->pitch,
    519                                      &nti->base.Map,
    520 				     ti->Width, ti->Height, depth,
    521 				     format, type, pixels, packing);
    522 		assert(ret);
    523 
    524 		nouveau_teximage_unmap(ctx, ti);
    525 		_mesa_unmap_teximage_pbo(ctx, packing);
    526 
    527 		if (!validate_teximage(ctx, t, level, 0, 0, 0,
    528 				       ti->Width, ti->Height, depth))
    529 			/* It doesn't fit, mark it as dirty. */
    530 			texture_dirty(t);
    531 	}
    532 
    533 	if (level == t->BaseLevel) {
    534 		if (!teximage_fits(t, level))
    535 			relayout_texture(ctx, t);
    536 		nouveau_texture_validate(ctx, t);
    537 	}
    538 
    539 	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    540 	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
    541 }
    542 
    543 
    544 static void
    545 nouveau_teximage_123d(struct gl_context *ctx, GLuint dims,
    546                       struct gl_texture_image *ti,
    547                       GLenum format, GLenum type, const GLvoid *pixels,
    548                       const struct gl_pixelstore_attrib *packing)
    549 {
    550 	nouveau_teximage(ctx, dims, ti, 0, format, type, pixels,
    551 			 packing, GL_FALSE);
    552 }
    553 
    554 static void
    555 nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims,
    556 		    struct gl_texture_image *ti,
    557 		    GLsizei imageSize, const GLvoid *data)
    558 {
    559 	nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data,
    560 			 &ctx->Unpack, GL_TRUE);
    561 }
    562 
    563 static void
    564 nouveau_texsubimage(struct gl_context *ctx, GLint dims,
    565 		    struct gl_texture_image *ti,
    566 		    GLint xoffset, GLint yoffset, GLint zoffset,
    567 		    GLint width, GLint height, GLint depth,
    568 		    GLsizei imageSize,
    569 		    GLenum format, GLenum type, const void *pixels,
    570 		    const struct gl_pixelstore_attrib *packing,
    571 		    GLboolean compressed)
    572 {
    573 	struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
    574 	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
    575 	int ret;
    576 
    577 	if (compressed)
    578 		pixels = _mesa_validate_pbo_compressed_teximage(ctx,
    579 				imageSize,
    580 				pixels, packing, "glCompressedTexSubImage");
    581 	else
    582 		pixels = _mesa_validate_pbo_teximage(ctx,
    583 				dims, width, height, depth, format, type,
    584 				pixels, packing, "glTexSubImage");
    585 
    586 	if (pixels) {
    587 		nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
    588 				     xoffset, yoffset, width, height);
    589 
    590 		ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, ti->TexFormat,
    591                                      s->pitch,
    592 				     &nti->base.Map,
    593                                      width, height, depth,
    594 				     format, type, pixels, packing);
    595 		assert(ret);
    596 
    597 		nouveau_teximage_unmap(ctx, ti);
    598 		_mesa_unmap_teximage_pbo(ctx, packing);
    599 	}
    600 
    601 	if (!to_nouveau_texture(ti->TexObject)->dirty)
    602 		validate_teximage(ctx, ti->TexObject, ti->Level,
    603 				  xoffset, yoffset, zoffset,
    604 				  width, height, depth);
    605 }
    606 
    607 static void
    608 nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims,
    609                          struct gl_texture_image *ti,
    610                          GLint xoffset, GLint yoffset, GLint zoffset,
    611                          GLint width, GLint height, GLint depth,
    612                          GLenum format, GLenum type, const void *pixels,
    613                          const struct gl_pixelstore_attrib *packing)
    614 {
    615 	nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
    616 			    width, height, depth, 0, format, type, pixels,
    617 			    packing, GL_FALSE);
    618 }
    619 
    620 static void
    621 nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
    622 		       struct gl_texture_image *ti,
    623 		       GLint xoffset, GLint yoffset, GLint zoffset,
    624 		       GLsizei width, GLint height, GLint depth,
    625 		       GLenum format,
    626 		       GLint imageSize, const void *data)
    627 {
    628 	nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
    629 			  width, height, depth, imageSize, format, 0, data,
    630 			  &ctx->Unpack, GL_TRUE);
    631 }
    632 
    633 static void
    634 nouveau_bind_texture(struct gl_context *ctx, GLenum target,
    635 		     struct gl_texture_object *t)
    636 {
    637 	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    638 	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
    639 }
    640 
    641 static gl_format
    642 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
    643 {
    644 	struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
    645 
    646 	if (s->cpp < 4)
    647 		return s->format;
    648 	else if (format == __DRI_TEXTURE_FORMAT_RGBA)
    649 		return MESA_FORMAT_ARGB8888;
    650 	else
    651 		return MESA_FORMAT_XRGB8888;
    652 }
    653 
    654 void
    655 nouveau_set_texbuffer(__DRIcontext *dri_ctx,
    656 		      GLint target, GLint format,
    657 		      __DRIdrawable *draw)
    658 {
    659 	struct nouveau_context *nctx = dri_ctx->driverPrivate;
    660 	struct gl_context *ctx = &nctx->base;
    661 	struct gl_framebuffer *fb = draw->driverPrivate;
    662 	struct gl_renderbuffer *rb =
    663 		fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
    664 	struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
    665 	struct gl_texture_image *ti;
    666 	struct nouveau_teximage *nti;
    667 	struct nouveau_surface *s;
    668 
    669 	_mesa_lock_texture(ctx, t);
    670 	ti = _mesa_get_tex_image(ctx, t, target, 0);
    671 	nti = to_nouveau_teximage(ti);
    672 	s = &to_nouveau_teximage(ti)->surface;
    673 
    674 	/* Update the texture surface with the given drawable. */
    675 	nouveau_update_renderbuffers(dri_ctx, draw);
    676 	nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
    677 
    678         s->format = get_texbuffer_format(rb, format);
    679 
    680 	/* Update the image fields. */
    681 	_mesa_init_teximage_fields(ctx, ti, s->width, s->height,
    682 				   1, 0, s->cpp, s->format);
    683 	nti->base.RowStride = s->pitch / s->cpp;
    684 
    685 	/* Try to validate it. */
    686 	if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
    687 		nouveau_texture_reallocate(ctx, t);
    688 
    689 	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
    690 	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
    691 
    692 	_mesa_unlock_texture(ctx, t);
    693 }
    694 
    695 void
    696 nouveau_texture_functions_init(struct dd_function_table *functions)
    697 {
    698 	functions->NewTextureObject = nouveau_texture_new;
    699 	functions->DeleteTexture = nouveau_texture_free;
    700 	functions->NewTextureImage = nouveau_teximage_new;
    701 	functions->FreeTextureImageBuffer = nouveau_teximage_free;
    702 	functions->ChooseTextureFormat = nouveau_choose_tex_format;
    703 	functions->TexImage = nouveau_teximage_123d;
    704 	functions->TexSubImage = nouveau_texsubimage_123d;
    705 	functions->CompressedTexImage = nouveau_compressed_teximage;
    706 	functions->CompressedTexSubImage = nouveau_compressed_texsubimage;
    707 	functions->BindTexture = nouveau_bind_texture;
    708 	functions->MapTextureImage = nouveau_map_texture_image;
    709 	functions->UnmapTextureImage = nouveau_unmap_texture_image;
    710 }
    711