• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
nouveau_texture_new(struct gl_context * ctx,GLuint name,GLenum target)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(ctx, &nt->base, name, target);
50 
51 	return &nt->base;
52 }
53 
54 static void
nouveau_texture_free(struct gl_context * ctx,struct gl_texture_object * t)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 *
nouveau_teximage_new(struct gl_context * ctx)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
nouveau_teximage_free(struct gl_context * ctx,struct gl_texture_image * ti)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
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)83 nouveau_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 
146 static void
nouveau_unmap_texture_image(struct gl_context * ctx,struct gl_texture_image * ti,GLuint slice)147 nouveau_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 
163 static mesa_format
nouveau_choose_tex_format(struct gl_context * ctx,GLenum target,GLint internalFormat,GLenum srcFormat,GLenum srcType)164 nouveau_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 
252 static GLboolean
teximage_fits(struct gl_texture_object * t,int level)253 teximage_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 
269 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)270 validate_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 
293 static int
get_last_level(struct gl_texture_object * t)294 get_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 
305 static void
relayout_texture(struct gl_context * ctx,struct gl_texture_object * t)306 relayout_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 
364 GLboolean
nouveau_texture_validate(struct gl_context * ctx,struct gl_texture_object * t)365 nouveau_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 
391 void
nouveau_texture_reallocate(struct gl_context * ctx,struct gl_texture_object * t)392 nouveau_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 
402 static unsigned
get_teximage_placement(struct gl_texture_image * ti)403 get_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 
415 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)416 nouveau_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 
440 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)441 nouveau_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 
513 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)514 nouveau_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 
523 static void
nouveau_compressed_teximage(struct gl_context * ctx,GLuint dims,struct gl_texture_image * ti,GLsizei imageSize,const GLvoid * data)524 nouveau_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 
532 static GLboolean
nouveau_teximage_alloc(struct gl_context * ctx,struct gl_texture_image * ti)533 nouveau_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 
541 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)542 nouveau_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 
593 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)594 nouveau_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 
606 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)607 nouveau_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 
619 static void
nouveau_bind_texture(struct gl_context * ctx,GLuint texUnit,GLenum target,struct gl_texture_object * t)620 nouveau_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 
627 static mesa_format
get_texbuffer_format(struct gl_renderbuffer * rb,GLint format)628 get_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 
640 void
nouveau_set_texbuffer(__DRIcontext * dri_ctx,GLint target,GLint format,__DRIdrawable * draw)641 nouveau_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 
681 void
nouveau_texture_functions_init(struct dd_function_table * functions)682 nouveau_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