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 
47 static struct gl_texture_object *
nouveau_texture_new(struct gl_context * ctx,GLuint name,GLenum target)48 nouveau_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 
57 static void
nouveau_texture_free(struct gl_context * ctx,struct gl_texture_object * t)58 nouveau_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 
69 static struct gl_texture_image *
nouveau_teximage_new(struct gl_context * ctx)70 nouveau_teximage_new(struct gl_context *ctx)
71 {
72 	struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
73 
74 	return &nti->base.Base;
75 }
76 
77 static void
nouveau_teximage_free(struct gl_context * ctx,struct gl_texture_image * ti)78 nouveau_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 
85 static void
nouveau_map_texture_image(struct gl_context * ctx,struct gl_texture_image * ti,GLuint slice,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** map,GLint * stride)86 nouveau_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 
149 static void
nouveau_unmap_texture_image(struct gl_context * ctx,struct gl_texture_image * ti,GLuint slice)150 nouveau_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 
166 static mesa_format
nouveau_choose_tex_format(struct gl_context * ctx,GLenum target,GLint internalFormat,GLenum srcFormat,GLenum srcType)167 nouveau_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 
255 static GLboolean
teximage_fits(struct gl_texture_object * t,int level)256 teximage_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 
272 static GLboolean
validate_teximage(struct gl_context * ctx,struct gl_texture_object * t,int level,int x,int y,int z,int width,int height,int depth)273 validate_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 
296 static int
get_last_level(struct gl_texture_object * t)297 get_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 
308 static void
relayout_texture(struct gl_context * ctx,struct gl_texture_object * t)309 relayout_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 
367 GLboolean
nouveau_texture_validate(struct gl_context * ctx,struct gl_texture_object * t)368 nouveau_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 
394 void
nouveau_texture_reallocate(struct gl_context * ctx,struct gl_texture_object * t)395 nouveau_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 
405 static unsigned
get_teximage_placement(struct gl_texture_image * ti)406 get_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 
418 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)419 nouveau_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 
443 static void
nouveau_teximage(struct gl_context * ctx,GLint dims,struct gl_texture_image * ti,GLsizei imageSize,GLenum format,GLenum type,const GLvoid * pixels,const struct gl_pixelstore_attrib * packing,GLboolean compressed)444 nouveau_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 
516 static void
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)517 nouveau_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 
526 static void
nouveau_compressed_teximage(struct gl_context * ctx,GLuint dims,struct gl_texture_image * ti,GLsizei imageSize,const GLvoid * data)527 nouveau_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 
535 static GLboolean
nouveau_teximage_alloc(struct gl_context * ctx,struct gl_texture_image * ti)536 nouveau_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 
544 static void
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,GLboolean compressed)545 nouveau_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 
596 static void
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)597 nouveau_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 
609 static void
nouveau_compressed_texsubimage(struct gl_context * ctx,GLuint dims,struct gl_texture_image * ti,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLint height,GLint depth,GLenum format,GLint imageSize,const void * data)610 nouveau_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 
622 static void
nouveau_bind_texture(struct gl_context * ctx,GLuint texUnit,GLenum target,struct gl_texture_object * t)623 nouveau_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 
630 static mesa_format
get_texbuffer_format(struct gl_renderbuffer * rb,GLint format)631 get_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 
643 void
nouveau_set_texbuffer(__DRIcontext * dri_ctx,GLint target,GLint format,__DRIdrawable * draw)644 nouveau_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 
684 void
nouveau_texture_functions_init(struct dd_function_table * functions)685 nouveau_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