2 * Copyright (C) 2009 Francisco Jerez.
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:
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.
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.
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"
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"
44 static struct gl_texture_object *
45 nouveau_texture_new(struct gl_context *ctx, GLuint name, GLenum target)
47 struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture);
49 _mesa_initialize_texture_object(&nt->base, name, target);
55 nouveau_texture_free(struct gl_context *ctx, struct gl_texture_object *t)
57 struct nouveau_texture *nt = to_nouveau_texture(t);
60 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
61 nouveau_surface_ref(NULL, &nt->surfaces[i]);
63 _mesa_delete_texture_object(ctx, t);
66 static struct gl_texture_image *
67 nouveau_teximage_new(struct gl_context *ctx)
69 struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
71 return &nti->base.Base;
75 nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti)
77 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
79 nouveau_surface_ref(NULL, &nti->surface);
83 nouveau_teximage_map(struct gl_context *ctx, struct gl_texture_image *ti,
84 int access, int x, int y, int w, int h)
86 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
87 struct nouveau_surface *s = &nti->surface;
88 struct nouveau_surface *st = &nti->transfer.surface;
91 if (!(access & GL_MAP_READ_BIT) &&
92 nouveau_bo_pending(s->bo)) {
94 * Heuristic: use a bounce buffer to pipeline
98 st->format = s->format;
102 st->pitch = s->pitch;
106 nti->base.Map = nouveau_get_scratch(ctx, st->pitch * h,
107 &st->bo, &st->offset);
112 if (access & GL_MAP_READ_BIT)
113 flags |= NOUVEAU_BO_RD;
114 if (access & GL_MAP_WRITE_BIT)
115 flags |= NOUVEAU_BO_WR;
118 ret = nouveau_bo_map(s->bo, flags);
122 nti->base.Map = s->bo->map + y * s->pitch + x * s->cpp;
128 nouveau_teximage_unmap(struct gl_context *ctx, struct gl_texture_image *ti)
130 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
131 struct nouveau_surface *s = &nti->surface;
132 struct nouveau_surface *st = &nti->transfer.surface;
135 context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x,
136 nti->transfer.y, 0, 0,
137 st->width, st->height);
138 nouveau_surface_ref(NULL, st);
141 nouveau_bo_unmap(s->bo);
144 nti->base.Map = NULL;
149 nouveau_map_texture_image(struct gl_context *ctx,
150 struct gl_texture_image *ti,
152 GLuint x, GLuint y, GLuint w, GLuint h,
157 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
158 struct nouveau_surface *s = &nti->surface;
159 struct nouveau_surface *st = &nti->transfer.surface;
161 /* Nouveau has no support for 3D or cubemap textures. */
165 if (!(mode & GL_MAP_READ_BIT) &&
166 nouveau_bo_pending(s->bo)) {
168 * Heuristic: use a bounce buffer to pipeline
169 * teximage transfers.
172 st->format = s->format;
176 st->pitch = s->pitch;
180 *map = nouveau_get_scratch(ctx, st->pitch * h,
181 &st->bo, &st->offset);
186 if (mode & GL_MAP_READ_BIT)
187 flags |= NOUVEAU_BO_RD;
188 if (mode & GL_MAP_WRITE_BIT)
189 flags |= NOUVEAU_BO_WR;
192 ret = nouveau_bo_map(s->bo, flags);
196 *map = s->bo->map + y * s->pitch + x * s->cpp;
200 *map = nti->base.Map + y * s->pitch + x * s->cpp;
206 nouveau_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *ti,
209 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
210 struct nouveau_surface *s = &nti->surface;
211 struct nouveau_surface *st = &nti->transfer.surface;
214 context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x,
215 nti->transfer.y, 0, 0,
216 st->width, st->height);
217 nouveau_surface_ref(NULL, st);
220 nouveau_bo_unmap(s->bo);
223 nti->base.Map = NULL;
227 nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat,
228 GLenum srcFormat, GLenum srcType)
230 switch (internalFormat) {
239 case GL_COMPRESSED_RGBA:
240 return MESA_FORMAT_ARGB8888;
242 return MESA_FORMAT_ARGB1555;
249 case GL_COMPRESSED_RGB:
250 return MESA_FORMAT_XRGB8888;
255 return MESA_FORMAT_RGB565;
258 case GL_LUMINANCE_ALPHA:
259 case GL_LUMINANCE4_ALPHA4:
260 case GL_LUMINANCE6_ALPHA2:
261 case GL_LUMINANCE12_ALPHA4:
262 case GL_LUMINANCE12_ALPHA12:
263 case GL_LUMINANCE16_ALPHA16:
264 case GL_LUMINANCE8_ALPHA8:
265 case GL_COMPRESSED_LUMINANCE_ALPHA:
266 return MESA_FORMAT_ARGB8888;
274 case GL_COMPRESSED_LUMINANCE:
275 return MESA_FORMAT_L8;
282 case GL_COMPRESSED_ALPHA:
283 return MESA_FORMAT_A8;
290 return MESA_FORMAT_I8;
298 teximage_fits(struct gl_texture_object *t, int level)
300 struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
301 struct gl_texture_image *ti = t->Image[0][level];
303 if (!ti || !to_nouveau_teximage(ti)->surface.bo)
306 if (level == t->BaseLevel && (s->offset & 0x7f))
309 return t->Target == GL_TEXTURE_RECTANGLE ||
310 (s->bo && s->format == ti->TexFormat &&
311 s->width == ti->Width && s->height == ti->Height);
315 validate_teximage(struct gl_context *ctx, struct gl_texture_object *t,
316 int level, int x, int y, int z,
317 int width, int height, int depth)
319 struct gl_texture_image *ti = t->Image[0][level];
321 if (teximage_fits(t, level)) {
322 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
323 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
325 if (t->Target == GL_TEXTURE_RECTANGLE)
326 nouveau_surface_ref(s, &ss[level]);
328 context_drv(ctx)->surface_copy(ctx, &ss[level], s,
339 get_last_level(struct gl_texture_object *t)
341 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
343 if (t->Sampler.MinFilter == GL_NEAREST ||
344 t->Sampler.MinFilter == GL_LINEAR || !base)
347 return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel);
351 relayout_texture(struct gl_context *ctx, struct gl_texture_object *t)
353 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
355 if (base && t->Target != GL_TEXTURE_RECTANGLE) {
356 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
357 struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
358 int i, ret, last = get_last_level(t);
359 unsigned size, offset = 0,
363 /* Deallocate the old storage. */
364 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
365 nouveau_bo_ref(NULL, &ss[i].bo);
367 /* Relayout the mipmap tree. */
368 for (i = t->BaseLevel; i <= last; i++) {
369 size = width * height * s->cpp;
371 /* Images larger than 16B have to be aligned. */
373 offset = align(offset, 64);
375 ss[i] = (struct nouveau_surface) {
382 .pitch = width * s->cpp,
386 width = MAX2(1, width / 2);
387 height = MAX2(1, height / 2);
390 /* Get new storage. */
391 size = align(offset, 64);
393 ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
394 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
395 0, size, &ss[last].bo);
398 for (i = t->BaseLevel; i < last; i++)
399 nouveau_bo_ref(ss[last].bo, &ss[i].bo);
404 nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t)
406 struct nouveau_texture *nt = to_nouveau_texture(t);
407 int i, last = get_last_level(t);
409 if (!teximage_fits(t, t->BaseLevel) ||
410 !teximage_fits(t, last))
414 nt->dirty = GL_FALSE;
416 /* Copy the teximages to the actual miptree. */
417 for (i = t->BaseLevel; i <= last; i++) {
418 struct nouveau_surface *s = &nt->surfaces[i];
420 validate_teximage(ctx, t, i, 0, 0, 0,
421 s->width, s->height, 1);
424 FIRE_RING(context_chan(ctx));
431 nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t)
433 if (!teximage_fits(t, t->BaseLevel) ||
434 !teximage_fits(t, get_last_level(t))) {
436 relayout_texture(ctx, t);
437 nouveau_texture_validate(ctx, t);
442 get_teximage_placement(struct gl_texture_image *ti)
444 if (ti->TexFormat == MESA_FORMAT_A8 ||
445 ti->TexFormat == MESA_FORMAT_L8 ||
446 ti->TexFormat == MESA_FORMAT_I8)
447 /* 1 cpp formats will have to be swizzled by the CPU,
448 * so leave them in system RAM for now. */
449 return NOUVEAU_BO_MAP;
451 return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
455 nouveau_teximage(struct gl_context *ctx, GLint dims,
456 struct gl_texture_image *ti,
457 GLint internalFormat,
458 GLint width, GLint height, GLint depth, GLint border,
459 GLenum format, GLenum type, const GLvoid *pixels,
460 const struct gl_pixelstore_attrib *packing)
462 struct gl_texture_object *t = ti->TexObject;
463 const GLuint level = ti->Level;
464 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
465 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
468 /* Allocate a new bo for the image. */
469 nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
470 ti->TexFormat, width, height);
471 nti->base.RowStride = s->pitch / s->cpp;
473 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
474 format, type, pixels, packing,
477 /* Store the pixel data. */
478 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
479 0, 0, width, height);
481 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
485 width, height, depth,
486 format, type, pixels, packing);
489 nouveau_teximage_unmap(ctx, ti);
490 _mesa_unmap_teximage_pbo(ctx, packing);
492 if (!validate_teximage(ctx, t, level, 0, 0, 0,
493 width, height, depth))
494 /* It doesn't fit, mark it as dirty. */
498 if (level == t->BaseLevel) {
499 if (!teximage_fits(t, level))
500 relayout_texture(ctx, t);
501 nouveau_texture_validate(ctx, t);
504 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
505 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
509 nouveau_teximage_1d(struct gl_context *ctx,
510 struct gl_texture_image *ti,
511 GLint internalFormat,
512 GLint width, GLint border,
513 GLenum format, GLenum type, const GLvoid *pixels,
514 const struct gl_pixelstore_attrib *packing)
516 nouveau_teximage(ctx, 1, ti, internalFormat,
517 width, 1, 1, border, format, type, pixels,
522 nouveau_teximage_2d(struct gl_context *ctx,
523 struct gl_texture_image *ti,
524 GLint internalFormat,
525 GLint width, GLint height, GLint border,
526 GLenum format, GLenum type, const GLvoid *pixels,
527 const struct gl_pixelstore_attrib *packing)
529 nouveau_teximage(ctx, 2, ti, internalFormat,
530 width, height, 1, border, format, type, pixels,
535 nouveau_teximage_3d(struct gl_context *ctx,
536 struct gl_texture_image *ti,
537 GLint internalFormat,
538 GLint width, GLint height, GLint depth, GLint border,
539 GLenum format, GLenum type, const GLvoid *pixels,
540 const struct gl_pixelstore_attrib *packing)
542 nouveau_teximage(ctx, 3, ti, internalFormat,
543 width, height, depth, border, format, type, pixels,
548 nouveau_texsubimage(struct gl_context *ctx, GLint dims,
549 struct gl_texture_image *ti,
550 GLint xoffset, GLint yoffset, GLint zoffset,
551 GLint width, GLint height, GLint depth,
552 GLenum format, GLenum type, const void *pixels,
553 const struct gl_pixelstore_attrib *packing)
555 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
556 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
559 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
560 format, type, pixels, packing,
563 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
564 xoffset, yoffset, width, height);
566 ret = _mesa_texstore(ctx, 3, ti->_BaseFormat, ti->TexFormat,
569 width, height, depth,
570 format, type, pixels, packing);
573 nouveau_teximage_unmap(ctx, ti);
574 _mesa_unmap_teximage_pbo(ctx, packing);
577 if (!to_nouveau_texture(ti->TexObject)->dirty)
578 validate_teximage(ctx, ti->TexObject, ti->Level,
579 xoffset, yoffset, zoffset,
580 width, height, depth);
584 nouveau_texsubimage_3d(struct gl_context *ctx,
585 struct gl_texture_image *ti,
586 GLint xoffset, GLint yoffset, GLint zoffset,
587 GLint width, GLint height, GLint depth,
588 GLenum format, GLenum type, const void *pixels,
589 const struct gl_pixelstore_attrib *packing)
591 nouveau_texsubimage(ctx, 3, ti, xoffset, yoffset, zoffset,
592 width, height, depth, format, type, pixels,
597 nouveau_texsubimage_2d(struct gl_context *ctx,
598 struct gl_texture_image *ti,
599 GLint xoffset, GLint yoffset,
600 GLint width, GLint height,
601 GLenum format, GLenum type, const void *pixels,
602 const struct gl_pixelstore_attrib *packing)
604 nouveau_texsubimage(ctx, 2, ti, xoffset, yoffset, 0,
605 width, height, 1, format, type, pixels,
610 nouveau_texsubimage_1d(struct gl_context *ctx,
611 struct gl_texture_image *ti,
612 GLint xoffset, GLint width,
613 GLenum format, GLenum type, const void *pixels,
614 const struct gl_pixelstore_attrib *packing)
616 nouveau_texsubimage(ctx, 1, ti, xoffset, 0, 0,
617 width, 1, 1, format, type, pixels,
622 nouveau_bind_texture(struct gl_context *ctx, GLenum target,
623 struct gl_texture_object *t)
625 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
626 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
630 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
632 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
636 else if (format == __DRI_TEXTURE_FORMAT_RGBA)
637 return MESA_FORMAT_ARGB8888;
639 return MESA_FORMAT_XRGB8888;
643 nouveau_set_texbuffer(__DRIcontext *dri_ctx,
644 GLint target, GLint format,
647 struct nouveau_context *nctx = dri_ctx->driverPrivate;
648 struct gl_context *ctx = &nctx->base;
649 struct gl_framebuffer *fb = draw->driverPrivate;
650 struct gl_renderbuffer *rb =
651 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
652 struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
653 struct gl_texture_image *ti;
654 struct nouveau_teximage *nti;
655 struct nouveau_surface *s;
657 _mesa_lock_texture(ctx, t);
658 ti = _mesa_get_tex_image(ctx, t, target, 0);
659 nti = to_nouveau_teximage(ti);
660 s = &to_nouveau_teximage(ti)->surface;
662 /* Update the texture surface with the given drawable. */
663 nouveau_update_renderbuffers(dri_ctx, draw);
664 nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
666 s->format = get_texbuffer_format(rb, format);
668 /* Update the image fields. */
669 _mesa_init_teximage_fields(ctx, ti, s->width, s->height,
670 1, 0, s->cpp, s->format);
671 nti->base.RowStride = s->pitch / s->cpp;
673 /* Try to validate it. */
674 if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
675 nouveau_texture_reallocate(ctx, t);
677 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
678 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
680 _mesa_unlock_texture(ctx, t);
684 nouveau_texture_map(struct gl_context *ctx, struct gl_texture_object *t)
688 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
689 struct gl_texture_image *ti = t->Image[0][i];
692 nouveau_teximage_map(ctx, ti, GL_MAP_READ_BIT,
693 0, 0, ti->Width, ti->Height);
698 nouveau_texture_unmap(struct gl_context *ctx, struct gl_texture_object *t)
702 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
704 nouveau_teximage_unmap(ctx, t->Image[0][i]);
709 nouveau_texture_functions_init(struct dd_function_table *functions)
711 functions->NewTextureObject = nouveau_texture_new;
712 functions->DeleteTexture = nouveau_texture_free;
713 functions->NewTextureImage = nouveau_teximage_new;
714 functions->FreeTextureImageBuffer = nouveau_teximage_free;
715 functions->ChooseTextureFormat = nouveau_choose_tex_format;
716 functions->TexImage1D = nouveau_teximage_1d;
717 functions->TexImage2D = nouveau_teximage_2d;
718 functions->TexImage3D = nouveau_teximage_3d;
719 functions->TexSubImage1D = nouveau_texsubimage_1d;
720 functions->TexSubImage2D = nouveau_texsubimage_2d;
721 functions->TexSubImage3D = nouveau_texsubimage_3d;
722 functions->BindTexture = nouveau_bind_texture;
723 functions->MapTexture = nouveau_texture_map;
724 functions->UnmapTexture = nouveau_texture_unmap;
725 functions->MapTextureImage = nouveau_map_texture_image;
726 functions->UnmapTextureImage = nouveau_unmap_texture_image;