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