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