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/texfetch.h"
41 #include "main/teximage.h"
42 #include "drivers/common/meta.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);
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 ti->Data = 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 ti->Data = 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);
148 nouveau_choose_tex_format(struct gl_context *ctx, GLint internalFormat,
149 GLenum srcFormat, GLenum srcType)
151 switch (internalFormat) {
160 case GL_COMPRESSED_RGBA:
161 return MESA_FORMAT_ARGB8888;
163 return MESA_FORMAT_ARGB1555;
170 case GL_COMPRESSED_RGB:
171 return MESA_FORMAT_XRGB8888;
176 return MESA_FORMAT_RGB565;
179 case GL_LUMINANCE_ALPHA:
180 case GL_LUMINANCE4_ALPHA4:
181 case GL_LUMINANCE6_ALPHA2:
182 case GL_LUMINANCE12_ALPHA4:
183 case GL_LUMINANCE12_ALPHA12:
184 case GL_LUMINANCE16_ALPHA16:
185 case GL_LUMINANCE8_ALPHA8:
186 case GL_COMPRESSED_LUMINANCE_ALPHA:
187 return MESA_FORMAT_ARGB8888;
195 case GL_COMPRESSED_LUMINANCE:
196 return MESA_FORMAT_L8;
203 case GL_COMPRESSED_ALPHA:
204 return MESA_FORMAT_A8;
211 return MESA_FORMAT_I8;
214 case GL_COLOR_INDEX1_EXT:
215 case GL_COLOR_INDEX2_EXT:
216 case GL_COLOR_INDEX4_EXT:
217 case GL_COLOR_INDEX12_EXT:
218 case GL_COLOR_INDEX16_EXT:
219 case GL_COLOR_INDEX8_EXT:
220 return MESA_FORMAT_CI8;
228 teximage_fits(struct gl_texture_object *t, int level)
230 struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
231 struct gl_texture_image *ti = t->Image[0][level];
233 if (!ti || !to_nouveau_teximage(ti)->surface.bo)
236 if (level == t->BaseLevel && (s->offset & 0x7f))
239 return t->Target == GL_TEXTURE_RECTANGLE ||
240 (s->bo && s->format == ti->TexFormat &&
241 s->width == ti->Width && s->height == ti->Height);
245 validate_teximage(struct gl_context *ctx, struct gl_texture_object *t,
246 int level, int x, int y, int z,
247 int width, int height, int depth)
249 struct gl_texture_image *ti = t->Image[0][level];
251 if (teximage_fits(t, level)) {
252 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
253 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
255 if (t->Target == GL_TEXTURE_RECTANGLE)
256 nouveau_surface_ref(s, &ss[level]);
258 context_drv(ctx)->surface_copy(ctx, &ss[level], s,
269 get_last_level(struct gl_texture_object *t)
271 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
273 if (t->Sampler.MinFilter == GL_NEAREST ||
274 t->Sampler.MinFilter == GL_LINEAR || !base)
277 return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel);
281 relayout_texture(struct gl_context *ctx, struct gl_texture_object *t)
283 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
285 if (base && t->Target != GL_TEXTURE_RECTANGLE) {
286 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
287 struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
288 int i, ret, last = get_last_level(t);
289 unsigned size, offset = 0,
293 /* Deallocate the old storage. */
294 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
295 nouveau_bo_ref(NULL, &ss[i].bo);
297 /* Relayout the mipmap tree. */
298 for (i = t->BaseLevel; i <= last; i++) {
299 size = width * height * s->cpp;
301 /* Images larger than 16B have to be aligned. */
303 offset = align(offset, 64);
305 ss[i] = (struct nouveau_surface) {
312 .pitch = width * s->cpp,
316 width = MAX2(1, width / 2);
317 height = MAX2(1, height / 2);
320 /* Get new storage. */
321 size = align(offset, 64);
323 ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
324 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
325 0, size, &ss[last].bo);
328 for (i = t->BaseLevel; i < last; i++)
329 nouveau_bo_ref(ss[last].bo, &ss[i].bo);
334 nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t)
336 struct nouveau_texture *nt = to_nouveau_texture(t);
337 int i, last = get_last_level(t);
339 if (!teximage_fits(t, t->BaseLevel) ||
340 !teximage_fits(t, last))
344 nt->dirty = GL_FALSE;
346 /* Copy the teximages to the actual miptree. */
347 for (i = t->BaseLevel; i <= last; i++) {
348 struct nouveau_surface *s = &nt->surfaces[i];
350 validate_teximage(ctx, t, i, 0, 0, 0,
351 s->width, s->height, 1);
354 FIRE_RING(context_chan(ctx));
361 nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t)
363 if (!teximage_fits(t, t->BaseLevel) ||
364 !teximage_fits(t, get_last_level(t))) {
366 relayout_texture(ctx, t);
367 nouveau_texture_validate(ctx, t);
372 get_teximage_placement(struct gl_texture_image *ti)
374 if (ti->TexFormat == MESA_FORMAT_A8 ||
375 ti->TexFormat == MESA_FORMAT_L8 ||
376 ti->TexFormat == MESA_FORMAT_I8)
377 /* 1 cpp formats will have to be swizzled by the CPU,
378 * so leave them in system RAM for now. */
379 return NOUVEAU_BO_MAP;
381 return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
385 nouveau_teximage(struct gl_context *ctx, GLint dims, GLenum target, GLint level,
386 GLint internalFormat,
387 GLint width, GLint height, GLint depth, GLint border,
388 GLenum format, GLenum type, const GLvoid *pixels,
389 const struct gl_pixelstore_attrib *packing,
390 struct gl_texture_object *t,
391 struct gl_texture_image *ti)
393 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
396 /* Allocate a new bo for the image. */
397 nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
398 ti->TexFormat, width, height);
399 ti->RowStride = s->pitch / s->cpp;
401 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
402 format, type, pixels, packing,
405 /* Store the pixel data. */
406 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
407 0, 0, width, height);
409 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
410 ti->TexFormat, ti->Data,
413 width, height, depth,
414 format, type, pixels, packing);
417 nouveau_teximage_unmap(ctx, ti);
418 _mesa_unmap_teximage_pbo(ctx, packing);
420 if (!validate_teximage(ctx, t, level, 0, 0, 0,
421 width, height, depth))
422 /* It doesn't fit, mark it as dirty. */
426 if (level == t->BaseLevel) {
427 if (!teximage_fits(t, level))
428 relayout_texture(ctx, t);
429 nouveau_texture_validate(ctx, t);
432 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
433 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
437 nouveau_teximage_1d(struct gl_context *ctx, GLenum target, GLint level,
438 GLint internalFormat,
439 GLint width, GLint border,
440 GLenum format, GLenum type, const GLvoid *pixels,
441 const struct gl_pixelstore_attrib *packing,
442 struct gl_texture_object *t,
443 struct gl_texture_image *ti)
445 nouveau_teximage(ctx, 1, target, level, internalFormat,
446 width, 1, 1, border, format, type, pixels,
451 nouveau_teximage_2d(struct gl_context *ctx, GLenum target, GLint level,
452 GLint internalFormat,
453 GLint width, GLint height, GLint border,
454 GLenum format, GLenum type, const GLvoid *pixels,
455 const struct gl_pixelstore_attrib *packing,
456 struct gl_texture_object *t,
457 struct gl_texture_image *ti)
459 nouveau_teximage(ctx, 2, target, level, internalFormat,
460 width, height, 1, border, format, type, pixels,
465 nouveau_teximage_3d(struct gl_context *ctx, GLenum target, GLint level,
466 GLint internalFormat,
467 GLint width, GLint height, GLint depth, GLint border,
468 GLenum format, GLenum type, const GLvoid *pixels,
469 const struct gl_pixelstore_attrib *packing,
470 struct gl_texture_object *t,
471 struct gl_texture_image *ti)
473 nouveau_teximage(ctx, 3, target, level, internalFormat,
474 width, height, depth, border, format, type, pixels,
479 nouveau_texsubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level,
480 GLint xoffset, GLint yoffset, GLint zoffset,
481 GLint width, GLint height, GLint depth,
482 GLenum format, GLenum type, const void *pixels,
483 const struct gl_pixelstore_attrib *packing,
484 struct gl_texture_object *t,
485 struct gl_texture_image *ti)
487 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
490 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
491 format, type, pixels, packing,
494 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT,
495 xoffset, yoffset, width, height);
497 ret = _mesa_texstore(ctx, 3, ti->_BaseFormat, ti->TexFormat,
498 ti->Data, 0, 0, 0, s->pitch,
499 ti->ImageOffsets, width, height, depth,
500 format, type, pixels, packing);
503 nouveau_teximage_unmap(ctx, ti);
504 _mesa_unmap_teximage_pbo(ctx, packing);
507 if (!to_nouveau_texture(t)->dirty)
508 validate_teximage(ctx, t, level, xoffset, yoffset, zoffset,
509 width, height, depth);
513 nouveau_texsubimage_3d(struct gl_context *ctx, GLenum target, GLint level,
514 GLint xoffset, GLint yoffset, GLint zoffset,
515 GLint width, GLint height, GLint depth,
516 GLenum format, GLenum type, const void *pixels,
517 const struct gl_pixelstore_attrib *packing,
518 struct gl_texture_object *t,
519 struct gl_texture_image *ti)
521 nouveau_texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
522 width, height, depth, format, type, pixels,
527 nouveau_texsubimage_2d(struct gl_context *ctx, GLenum target, GLint level,
528 GLint xoffset, GLint yoffset,
529 GLint width, GLint height,
530 GLenum format, GLenum type, const void *pixels,
531 const struct gl_pixelstore_attrib *packing,
532 struct gl_texture_object *t,
533 struct gl_texture_image *ti)
535 nouveau_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0,
536 width, height, 1, format, type, pixels,
541 nouveau_texsubimage_1d(struct gl_context *ctx, GLenum target, GLint level,
542 GLint xoffset, GLint width,
543 GLenum format, GLenum type, const void *pixels,
544 const struct gl_pixelstore_attrib *packing,
545 struct gl_texture_object *t,
546 struct gl_texture_image *ti)
548 nouveau_texsubimage(ctx, 1, target, level, xoffset, 0, 0,
549 width, 1, 1, format, type, pixels,
554 nouveau_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
555 GLenum format, GLenum type, GLvoid *pixels,
556 struct gl_texture_object *t,
557 struct gl_texture_image *ti)
559 nouveau_teximage_map(ctx, ti, GL_MAP_READ_BIT,
560 0, 0, ti->Width, ti->Height);
561 _mesa_get_teximage(ctx, target, level, format, type, pixels,
563 nouveau_teximage_unmap(ctx, ti);
567 nouveau_bind_texture(struct gl_context *ctx, GLenum target,
568 struct gl_texture_object *t)
570 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
571 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
575 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
577 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
581 else if (format == __DRI_TEXTURE_FORMAT_RGBA)
582 return MESA_FORMAT_ARGB8888;
584 return MESA_FORMAT_XRGB8888;
588 nouveau_set_texbuffer(__DRIcontext *dri_ctx,
589 GLint target, GLint format,
592 struct nouveau_context *nctx = dri_ctx->driverPrivate;
593 struct gl_context *ctx = &nctx->base;
594 struct gl_framebuffer *fb = draw->driverPrivate;
595 struct gl_renderbuffer *rb =
596 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
597 struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
598 struct gl_texture_image *ti;
599 struct nouveau_surface *s;
601 _mesa_lock_texture(ctx, t);
602 ti = _mesa_get_tex_image(ctx, t, target, 0);
603 s = &to_nouveau_teximage(ti)->surface;
605 /* Update the texture surface with the given drawable. */
606 nouveau_update_renderbuffers(dri_ctx, draw);
607 nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
609 s->format = get_texbuffer_format(rb, format);
611 /* Update the image fields. */
612 _mesa_init_teximage_fields(ctx, target, ti, s->width, s->height,
613 1, 0, s->cpp, s->format);
614 ti->RowStride = s->pitch / s->cpp;
616 /* Try to validate it. */
617 if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
618 nouveau_texture_reallocate(ctx, t);
620 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
621 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
623 _mesa_unlock_texture(ctx, t);
627 nouveau_texture_map(struct gl_context *ctx, struct gl_texture_object *t)
631 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
632 struct gl_texture_image *ti = t->Image[0][i];
635 nouveau_teximage_map(ctx, ti, GL_MAP_READ_BIT,
636 0, 0, ti->Width, ti->Height);
641 nouveau_texture_unmap(struct gl_context *ctx, struct gl_texture_object *t)
645 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
647 nouveau_teximage_unmap(ctx, t->Image[0][i]);
652 store_mipmap(struct gl_context *ctx, GLenum target, int first, int last,
653 struct gl_texture_object *t)
655 struct gl_pixelstore_attrib packing = {
656 .BufferObj = ctx->Shared->NullBufferObj,
659 GLenum format = t->Image[0][t->BaseLevel]->TexFormat;
660 unsigned base_format, type, comps;
663 base_format = _mesa_get_format_base_format(format);
664 _mesa_format_to_type_and_comps(format, &type, &comps);
666 for (i = first; i <= last; i++) {
667 struct gl_texture_image *ti = t->Image[0][i];
668 void *data = ti->Data;
670 nouveau_teximage(ctx, 3, target, i, ti->InternalFormat,
671 ti->Width, ti->Height, ti->Depth,
672 ti->Border, base_format, type, data,
675 _mesa_free_texmemory(data);
680 nouveau_generate_mipmap(struct gl_context *ctx, GLenum target,
681 struct gl_texture_object *t)
683 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, t)) {
684 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
686 nouveau_teximage_map(ctx, base, GL_MAP_READ_BIT,
687 0, 0, base->Width, base->Height);
688 _mesa_generate_mipmap(ctx, target, t);
689 nouveau_teximage_unmap(ctx, base);
691 if (!_mesa_is_format_compressed(base->TexFormat)) {
692 store_mipmap(ctx, target, t->BaseLevel + 1,
693 get_last_level(t), t);
697 _mesa_meta_GenerateMipmap(ctx, target, t);
702 nouveau_texture_functions_init(struct dd_function_table *functions)
704 functions->NewTextureObject = nouveau_texture_new;
705 functions->DeleteTexture = nouveau_texture_free;
706 functions->NewTextureImage = nouveau_teximage_new;
707 functions->FreeTexImageData = nouveau_teximage_free;
708 functions->ChooseTextureFormat = nouveau_choose_tex_format;
709 functions->TexImage1D = nouveau_teximage_1d;
710 functions->TexImage2D = nouveau_teximage_2d;
711 functions->TexImage3D = nouveau_teximage_3d;
712 functions->TexSubImage1D = nouveau_texsubimage_1d;
713 functions->TexSubImage2D = nouveau_texsubimage_2d;
714 functions->TexSubImage3D = nouveau_texsubimage_3d;
715 functions->GetTexImage = nouveau_get_teximage;
716 functions->BindTexture = nouveau_bind_texture;
717 functions->MapTexture = nouveau_texture_map;
718 functions->UnmapTexture = nouveau_texture_unmap;
719 functions->GenerateMipmap = nouveau_generate_mipmap;