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