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