nouveau_texture.c revision 5606bd574e264c4beda8eb1d10b48d17e9b8b497
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
44static struct gl_texture_object *
45nouveau_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
54static void
55nouveau_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
66static struct gl_texture_image *
67nouveau_teximage_new(struct gl_context *ctx)
68{
69	struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
70
71	return &nti->base.Base;
72}
73
74static void
75nouveau_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
82static void
83nouveau_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
133static void
134nouveau_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
151static void
152nouveau_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
215static void
216nouveau_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
234static gl_format
235nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat,
236			  GLenum srcFormat, GLenum srcType)
237{
238	switch (internalFormat) {
239	case 4:
240	case GL_RGBA:
241	case GL_RGBA2:
242	case GL_RGBA4:
243	case GL_RGBA8:
244	case GL_RGBA12:
245	case GL_RGBA16:
246	case GL_RGB10_A2:
247	case GL_COMPRESSED_RGBA:
248		return MESA_FORMAT_ARGB8888;
249	case GL_RGB5_A1:
250		return MESA_FORMAT_ARGB1555;
251
252	case GL_RGB:
253	case GL_RGB8:
254	case GL_RGB10:
255	case GL_RGB12:
256	case GL_RGB16:
257	case GL_COMPRESSED_RGB:
258		return MESA_FORMAT_XRGB8888;
259	case 3:
260	case GL_R3_G3_B2:
261	case GL_RGB4:
262	case GL_RGB5:
263		return MESA_FORMAT_RGB565;
264
265	case 2:
266	case GL_LUMINANCE_ALPHA:
267	case GL_LUMINANCE4_ALPHA4:
268	case GL_LUMINANCE6_ALPHA2:
269	case GL_LUMINANCE12_ALPHA4:
270	case GL_LUMINANCE12_ALPHA12:
271	case GL_LUMINANCE16_ALPHA16:
272	case GL_LUMINANCE8_ALPHA8:
273	case GL_COMPRESSED_LUMINANCE_ALPHA:
274		return MESA_FORMAT_ARGB8888;
275
276	case 1:
277	case GL_LUMINANCE:
278	case GL_LUMINANCE4:
279	case GL_LUMINANCE12:
280	case GL_LUMINANCE16:
281	case GL_LUMINANCE8:
282	case GL_COMPRESSED_LUMINANCE:
283		return MESA_FORMAT_L8;
284
285	case GL_ALPHA:
286	case GL_ALPHA4:
287	case GL_ALPHA12:
288	case GL_ALPHA16:
289	case GL_ALPHA8:
290	case GL_COMPRESSED_ALPHA:
291		return MESA_FORMAT_A8;
292
293	case GL_INTENSITY:
294	case GL_INTENSITY4:
295	case GL_INTENSITY12:
296	case GL_INTENSITY16:
297	case GL_INTENSITY8:
298		return MESA_FORMAT_I8;
299
300	case GL_RGB_S3TC:
301	case GL_RGB4_S3TC:
302	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
303		return MESA_FORMAT_RGB_DXT1;
304
305	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
306		return MESA_FORMAT_RGBA_DXT1;
307
308	case GL_RGBA_S3TC:
309	case GL_RGBA4_S3TC:
310	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
311		return MESA_FORMAT_RGBA_DXT3;
312
313	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
314		return MESA_FORMAT_RGBA_DXT5;
315
316	default:
317		assert(0);
318	}
319}
320
321static GLboolean
322teximage_fits(struct gl_texture_object *t, int level)
323{
324	struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
325	struct gl_texture_image *ti = t->Image[0][level];
326
327	if (!ti || !to_nouveau_teximage(ti)->surface.bo)
328		return GL_FALSE;
329
330	if (level == t->BaseLevel && (s->offset & 0x7f))
331		return GL_FALSE;
332
333	return t->Target == GL_TEXTURE_RECTANGLE ||
334		(s->bo && s->format == ti->TexFormat &&
335		 s->width == ti->Width && s->height == ti->Height);
336}
337
338static GLboolean
339validate_teximage(struct gl_context *ctx, struct gl_texture_object *t,
340		  int level, int x, int y, int z,
341		  int width, int height, int depth)
342{
343	struct gl_texture_image *ti = t->Image[0][level];
344
345	if (teximage_fits(t, level)) {
346		struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
347		struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
348
349		if (t->Target == GL_TEXTURE_RECTANGLE)
350			nouveau_surface_ref(s, &ss[level]);
351		else
352			context_drv(ctx)->surface_copy(ctx, &ss[level], s,
353						       x, y, x, y,
354						       width, height);
355
356		return GL_TRUE;
357	}
358
359	return GL_FALSE;
360}
361
362static int
363get_last_level(struct gl_texture_object *t)
364{
365	struct gl_texture_image *base = t->Image[0][t->BaseLevel];
366
367	if (t->Sampler.MinFilter == GL_NEAREST ||
368	    t->Sampler.MinFilter == GL_LINEAR || !base)
369		return t->BaseLevel;
370	else
371		return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel);
372}
373
374static void
375relayout_texture(struct gl_context *ctx, struct gl_texture_object *t)
376{
377	struct gl_texture_image *base = t->Image[0][t->BaseLevel];
378
379	if (base && t->Target != GL_TEXTURE_RECTANGLE) {
380		struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
381		struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
382		int i, ret, last = get_last_level(t);
383		enum nouveau_surface_layout layout =
384			(_mesa_is_format_compressed(s->format) ? LINEAR : SWIZZLED);
385		unsigned size, pitch, offset = 0,
386			width = s->width,
387			height = s->height;
388
389		/* Deallocate the old storage. */
390		for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
391			nouveau_bo_ref(NULL, &ss[i].bo);
392
393		/* Relayout the mipmap tree. */
394		for (i = t->BaseLevel; i <= last; i++) {
395			pitch = _mesa_format_row_stride(s->format, width);
396			size = get_format_blocksy(s->format, height) * pitch;
397
398			/* Images larger than 16B have to be aligned. */
399			if (size > 16)
400				offset = align(offset, 64);
401
402			ss[i] = (struct nouveau_surface) {
403				.offset = offset,
404				.layout = layout,
405				.format = s->format,
406				.width = width,
407				.height = height,
408				.cpp = s->cpp,
409				.pitch = pitch,
410			};
411
412			offset += size;
413			width = MAX2(1, width / 2);
414			height = MAX2(1, height / 2);
415		}
416
417		/* Get new storage. */
418		size = align(offset, 64);
419
420		ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
421				     NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
422				     0, size, NULL, &ss[last].bo);
423		assert(!ret);
424
425		for (i = t->BaseLevel; i < last; i++)
426			nouveau_bo_ref(ss[last].bo, &ss[i].bo);
427	}
428}
429
430GLboolean
431nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t)
432{
433	struct nouveau_texture *nt = to_nouveau_texture(t);
434	int i, last = get_last_level(t);
435
436	if (!teximage_fits(t, t->BaseLevel) ||
437	    !teximage_fits(t, last))
438		return GL_FALSE;
439
440	if (nt->dirty) {
441		nt->dirty = GL_FALSE;
442
443		/* Copy the teximages to the actual miptree. */
444		for (i = t->BaseLevel; i <= last; i++) {
445			struct nouveau_surface *s = &nt->surfaces[i];
446
447			validate_teximage(ctx, t, i, 0, 0, 0,
448					  s->width, s->height, 1);
449		}
450
451		PUSH_KICK(context_push(ctx));
452	}
453
454	return GL_TRUE;
455}
456
457void
458nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t)
459{
460	if (!teximage_fits(t, t->BaseLevel) ||
461	    !teximage_fits(t, get_last_level(t))) {
462		texture_dirty(t);
463		relayout_texture(ctx, t);
464		nouveau_texture_validate(ctx, t);
465	}
466}
467
468static unsigned
469get_teximage_placement(struct gl_texture_image *ti)
470{
471	if (ti->TexFormat == MESA_FORMAT_A8 ||
472	    ti->TexFormat == MESA_FORMAT_L8 ||
473	    ti->TexFormat == MESA_FORMAT_I8)
474		/* 1 cpp formats will have to be swizzled by the CPU,
475		 * so leave them in system RAM for now. */
476		return NOUVEAU_BO_MAP;
477	else
478		return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
479}
480
481static void
482nouveau_teximage(struct gl_context *ctx, GLint dims,
483		 struct gl_texture_image *ti,
484		 GLsizei imageSize,
485		 GLenum format, GLenum type, const GLvoid *pixels,
486		 const struct gl_pixelstore_attrib *packing,
487		 GLboolean compressed)
488{
489	struct gl_texture_object *t = ti->TexObject;
490	const GLuint level = ti->Level;
491	struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
492	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
493	int ret;
494	GLuint depth = compressed ? 1 : ti->Depth;
495
496	/* Allocate a new bo for the image. */
497	nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
498			      ti->TexFormat, ti->Width, ti->Height);
499	nti->base.RowStride = s->pitch / s->cpp;
500
501	if (compressed)
502		pixels = _mesa_validate_pbo_compressed_teximage(ctx,
503			imageSize,
504			pixels, packing, "glCompressedTexImage");
505	else
506		pixels = _mesa_validate_pbo_teximage(ctx,
507			dims, ti->Width, ti->Height, depth, format, type,
508			pixels, packing, "glTexImage");
509
510	if (pixels) {
511		/* Store the pixel data. */
512		nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
513				     0, 0, ti->Width, ti->Height);
514
515		ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
516				     ti->TexFormat,
517				     s->pitch,
518                                     &nti->base.Map,
519				     ti->Width, ti->Height, depth,
520				     format, type, pixels, packing);
521		assert(ret);
522
523		nouveau_teximage_unmap(ctx, ti);
524		_mesa_unmap_teximage_pbo(ctx, packing);
525
526		if (!validate_teximage(ctx, t, level, 0, 0, 0,
527				       ti->Width, ti->Height, depth))
528			/* It doesn't fit, mark it as dirty. */
529			texture_dirty(t);
530	}
531
532	if (level == t->BaseLevel) {
533		if (!teximage_fits(t, level))
534			relayout_texture(ctx, t);
535		nouveau_texture_validate(ctx, t);
536	}
537
538	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
539	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
540}
541
542
543static void
544nouveau_teximage_123d(struct gl_context *ctx, GLuint dims,
545                      struct gl_texture_image *ti,
546                      GLenum format, GLenum type, const GLvoid *pixels,
547                      const struct gl_pixelstore_attrib *packing)
548{
549	nouveau_teximage(ctx, dims, ti, 0, format, type, pixels,
550			 packing, GL_FALSE);
551}
552
553static void
554nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims,
555		    struct gl_texture_image *ti,
556		    GLsizei imageSize, const GLvoid *data)
557{
558	nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data,
559			 &ctx->Unpack, GL_TRUE);
560}
561
562static void
563nouveau_texsubimage(struct gl_context *ctx, GLint dims,
564		    struct gl_texture_image *ti,
565		    GLint xoffset, GLint yoffset, GLint zoffset,
566		    GLint width, GLint height, GLint depth,
567		    GLsizei imageSize,
568		    GLenum format, GLenum type, const void *pixels,
569		    const struct gl_pixelstore_attrib *packing,
570		    GLboolean compressed)
571{
572	struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
573	struct nouveau_teximage *nti = to_nouveau_teximage(ti);
574	int ret;
575
576	if (compressed)
577		pixels = _mesa_validate_pbo_compressed_teximage(ctx,
578				imageSize,
579				pixels, packing, "glCompressedTexSubImage");
580	else
581		pixels = _mesa_validate_pbo_teximage(ctx,
582				dims, width, height, depth, format, type,
583				pixels, packing, "glTexSubImage");
584
585	if (pixels) {
586		nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
587				     xoffset, yoffset, width, height);
588
589		ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, ti->TexFormat,
590                                     s->pitch,
591				     &nti->base.Map,
592                                     width, height, depth,
593				     format, type, pixels, packing);
594		assert(ret);
595
596		nouveau_teximage_unmap(ctx, ti);
597		_mesa_unmap_teximage_pbo(ctx, packing);
598	}
599
600	if (!to_nouveau_texture(ti->TexObject)->dirty)
601		validate_teximage(ctx, ti->TexObject, ti->Level,
602				  xoffset, yoffset, zoffset,
603				  width, height, depth);
604}
605
606static void
607nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims,
608                         struct gl_texture_image *ti,
609                         GLint xoffset, GLint yoffset, GLint zoffset,
610                         GLint width, GLint height, GLint depth,
611                         GLenum format, GLenum type, const void *pixels,
612                         const struct gl_pixelstore_attrib *packing)
613{
614	nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
615			    width, height, depth, 0, format, type, pixels,
616			    packing, GL_FALSE);
617}
618
619static void
620nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
621		       struct gl_texture_image *ti,
622		       GLint xoffset, GLint yoffset, GLint zoffset,
623		       GLsizei width, GLint height, GLint depth,
624		       GLenum format,
625		       GLint imageSize, const void *data)
626{
627	nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
628			  width, height, depth, imageSize, format, 0, data,
629			  &ctx->Unpack, GL_TRUE);
630}
631
632static void
633nouveau_bind_texture(struct gl_context *ctx, GLenum target,
634		     struct gl_texture_object *t)
635{
636	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
637	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
638}
639
640static gl_format
641get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
642{
643	struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
644
645	if (s->cpp < 4)
646		return s->format;
647	else if (format == __DRI_TEXTURE_FORMAT_RGBA)
648		return MESA_FORMAT_ARGB8888;
649	else
650		return MESA_FORMAT_XRGB8888;
651}
652
653void
654nouveau_set_texbuffer(__DRIcontext *dri_ctx,
655		      GLint target, GLint format,
656		      __DRIdrawable *draw)
657{
658	struct nouveau_context *nctx = dri_ctx->driverPrivate;
659	struct gl_context *ctx = &nctx->base;
660	struct gl_framebuffer *fb = draw->driverPrivate;
661	struct gl_renderbuffer *rb =
662		fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
663	struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
664	struct gl_texture_image *ti;
665	struct nouveau_teximage *nti;
666	struct nouveau_surface *s;
667
668	_mesa_lock_texture(ctx, t);
669	ti = _mesa_get_tex_image(ctx, t, target, 0);
670	nti = to_nouveau_teximage(ti);
671	s = &to_nouveau_teximage(ti)->surface;
672
673	/* Update the texture surface with the given drawable. */
674	nouveau_update_renderbuffers(dri_ctx, draw);
675	nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
676
677        s->format = get_texbuffer_format(rb, format);
678
679	/* Update the image fields. */
680	_mesa_init_teximage_fields(ctx, ti, s->width, s->height,
681				   1, 0, s->cpp, s->format);
682	nti->base.RowStride = s->pitch / s->cpp;
683
684	/* Try to validate it. */
685	if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
686		nouveau_texture_reallocate(ctx, t);
687
688	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
689	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
690
691	_mesa_unlock_texture(ctx, t);
692}
693
694void
695nouveau_texture_functions_init(struct dd_function_table *functions)
696{
697	functions->NewTextureObject = nouveau_texture_new;
698	functions->DeleteTexture = nouveau_texture_free;
699	functions->NewTextureImage = nouveau_teximage_new;
700	functions->FreeTextureImageBuffer = nouveau_teximage_free;
701	functions->ChooseTextureFormat = nouveau_choose_tex_format;
702	functions->TexImage = nouveau_teximage_123d;
703	functions->TexSubImage = nouveau_texsubimage_123d;
704	functions->CompressedTexImage = nouveau_compressed_teximage;
705	functions->CompressedTexSubImage = nouveau_compressed_texsubimage;
706	functions->BindTexture = nouveau_bind_texture;
707	functions->MapTextureImage = nouveau_map_texture_image;
708	functions->UnmapTextureImage = nouveau_unmap_texture_image;
709}
710