18dc9f7e6505bdb8124c53dd1fbd304ea05e4a4d
[profile/ivi/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                  GLsizei imageSize,
485                  GLenum format, GLenum type, const GLvoid *pixels,
486                  const struct gl_pixelstore_attrib *packing,
487                  GLboolean compressed)
488 {
489         struct gl_texture_object *t = ti->TexObject;
490         const GLuint level = ti->Level;
491         struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
492         struct nouveau_teximage *nti = to_nouveau_teximage(ti);
493         int ret;
494         GLuint depth = compressed ? 1 : ti->Depth;
495
496         /* Allocate a new bo for the image. */
497         nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
498                               ti->TexFormat, ti->Width, ti->Height);
499         nti->base.RowStride = s->pitch / s->cpp;
500
501         if (compressed)
502                 pixels = _mesa_validate_pbo_compressed_teximage(ctx,
503                         imageSize,
504                         pixels, packing, "glCompressedTexImage");
505         else
506                 pixels = _mesa_validate_pbo_teximage(ctx,
507                         dims, ti->Width, ti->Height, depth, format, type,
508                         pixels, packing, "glTexImage");
509
510         if (pixels) {
511                 /* Store the pixel data. */
512                 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
513                                      0, 0, ti->Width, ti->Height);
514
515                 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
516                                      ti->TexFormat,
517                                      s->pitch,
518                                      &nti->base.Map,
519                                      ti->Width, ti->Height, depth,
520                                      format, type, pixels, packing);
521                 assert(ret);
522
523                 nouveau_teximage_unmap(ctx, ti);
524                 _mesa_unmap_teximage_pbo(ctx, packing);
525
526                 if (!validate_teximage(ctx, t, level, 0, 0, 0,
527                                        ti->Width, ti->Height, depth))
528                         /* It doesn't fit, mark it as dirty. */
529                         texture_dirty(t);
530         }
531
532         if (level == t->BaseLevel) {
533                 if (!teximage_fits(t, level))
534                         relayout_texture(ctx, t);
535                 nouveau_texture_validate(ctx, t);
536         }
537
538         context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
539         context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
540 }
541
542
543 static void
544 nouveau_teximage_123d(struct gl_context *ctx, GLuint dims,
545                       struct gl_texture_image *ti,
546                       GLenum format, GLenum type, const GLvoid *pixels,
547                       const struct gl_pixelstore_attrib *packing)
548 {
549         nouveau_teximage(ctx, dims, ti, 0, format, type, pixels,
550                          packing, GL_FALSE);
551 }
552
553 static void
554 nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims,
555                     struct gl_texture_image *ti,
556                     GLint internalFormat,
557                     GLint width, GLint height, GLint depth, GLint border,
558                     GLsizei imageSize, const GLvoid *data)
559 {
560         nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data,
561                          &ctx->Unpack, GL_TRUE);
562 }
563
564 static void
565 nouveau_texsubimage(struct gl_context *ctx, GLint dims,
566                     struct gl_texture_image *ti,
567                     GLint xoffset, GLint yoffset, GLint zoffset,
568                     GLint width, GLint height, GLint depth,
569                     GLsizei imageSize,
570                     GLenum format, GLenum type, const void *pixels,
571                     const struct gl_pixelstore_attrib *packing,
572                     GLboolean compressed)
573 {
574         struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
575         struct nouveau_teximage *nti = to_nouveau_teximage(ti);
576         int ret;
577
578         if (compressed)
579                 pixels = _mesa_validate_pbo_compressed_teximage(ctx,
580                                 imageSize,
581                                 pixels, packing, "glCompressedTexSubImage");
582         else
583                 pixels = _mesa_validate_pbo_teximage(ctx,
584                                 dims, width, height, depth, format, type,
585                                 pixels, packing, "glTexSubImage");
586
587         if (pixels) {
588                 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
589                                      xoffset, yoffset, width, height);
590
591                 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, ti->TexFormat,
592                                      s->pitch,
593                                      &nti->base.Map,
594                                      width, height, depth,
595                                      format, type, pixels, packing);
596                 assert(ret);
597
598                 nouveau_teximage_unmap(ctx, ti);
599                 _mesa_unmap_teximage_pbo(ctx, packing);
600         }
601
602         if (!to_nouveau_texture(ti->TexObject)->dirty)
603                 validate_teximage(ctx, ti->TexObject, ti->Level,
604                                   xoffset, yoffset, zoffset,
605                                   width, height, depth);
606 }
607
608 static void
609 nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims,
610                          struct gl_texture_image *ti,
611                          GLint xoffset, GLint yoffset, GLint zoffset,
612                          GLint width, GLint height, GLint depth,
613                          GLenum format, GLenum type, const void *pixels,
614                          const struct gl_pixelstore_attrib *packing)
615 {
616         nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
617                             width, height, depth, 0, format, type, pixels,
618                             packing, GL_FALSE);
619 }
620
621 static void
622 nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
623                        struct gl_texture_image *ti,
624                        GLint xoffset, GLint yoffset, GLint zoffset,
625                        GLsizei width, GLint height, GLint depth,
626                        GLenum format,
627                        GLint imageSize, const void *data)
628 {
629         nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
630                           width, height, depth, imageSize, format, 0, data,
631                           &ctx->Unpack, GL_TRUE);
632 }
633
634 static void
635 nouveau_bind_texture(struct gl_context *ctx, GLenum target,
636                      struct gl_texture_object *t)
637 {
638         context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
639         context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
640 }
641
642 static gl_format
643 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
644 {
645         struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
646
647         if (s->cpp < 4)
648                 return s->format;
649         else if (format == __DRI_TEXTURE_FORMAT_RGBA)
650                 return MESA_FORMAT_ARGB8888;
651         else
652                 return MESA_FORMAT_XRGB8888;
653 }
654
655 void
656 nouveau_set_texbuffer(__DRIcontext *dri_ctx,
657                       GLint target, GLint format,
658                       __DRIdrawable *draw)
659 {
660         struct nouveau_context *nctx = dri_ctx->driverPrivate;
661         struct gl_context *ctx = &nctx->base;
662         struct gl_framebuffer *fb = draw->driverPrivate;
663         struct gl_renderbuffer *rb =
664                 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
665         struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
666         struct gl_texture_image *ti;
667         struct nouveau_teximage *nti;
668         struct nouveau_surface *s;
669
670         _mesa_lock_texture(ctx, t);
671         ti = _mesa_get_tex_image(ctx, t, target, 0);
672         nti = to_nouveau_teximage(ti);
673         s = &to_nouveau_teximage(ti)->surface;
674
675         /* Update the texture surface with the given drawable. */
676         nouveau_update_renderbuffers(dri_ctx, draw);
677         nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
678
679         s->format = get_texbuffer_format(rb, format);
680
681         /* Update the image fields. */
682         _mesa_init_teximage_fields(ctx, ti, s->width, s->height,
683                                    1, 0, s->cpp, s->format);
684         nti->base.RowStride = s->pitch / s->cpp;
685
686         /* Try to validate it. */
687         if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
688                 nouveau_texture_reallocate(ctx, t);
689
690         context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
691         context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
692
693         _mesa_unlock_texture(ctx, t);
694 }
695
696 void
697 nouveau_texture_functions_init(struct dd_function_table *functions)
698 {
699         functions->NewTextureObject = nouveau_texture_new;
700         functions->DeleteTexture = nouveau_texture_free;
701         functions->NewTextureImage = nouveau_teximage_new;
702         functions->FreeTextureImageBuffer = nouveau_teximage_free;
703         functions->ChooseTextureFormat = nouveau_choose_tex_format;
704         functions->TexImage = nouveau_teximage_123d;
705         functions->TexSubImage = nouveau_texsubimage_123d;
706         functions->CompressedTexImage = nouveau_compressed_teximage;
707         functions->CompressedTexSubImage = nouveau_compressed_texsubimage;
708         functions->BindTexture = nouveau_bind_texture;
709         functions->MapTextureImage = nouveau_map_texture_image;
710         functions->UnmapTextureImage = nouveau_unmap_texture_image;
711 }