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