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
;
89 struct nouveau_client
*client
= context_client(ctx
);
92 if (!(access
& GL_MAP_READ_BIT
) &&
93 nouveau_pushbuf_refd(context_push(ctx
), s
->bo
)) {
96 * Heuristic: use a bounce buffer to pipeline
100 st
->format
= s
->format
;
104 st
->pitch
= s
->pitch
;
108 size
= get_format_blocksy(st
->format
, h
) * st
->pitch
;
109 nti
->base
.Map
= nouveau_get_scratch(ctx
, size
,
110 &st
->bo
, &st
->offset
);
115 if (access
& GL_MAP_READ_BIT
)
116 flags
|= NOUVEAU_BO_RD
;
117 if (access
& GL_MAP_WRITE_BIT
)
118 flags
|= NOUVEAU_BO_WR
;
121 ret
= nouveau_bo_map(s
->bo
, flags
, client
);
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
;
134 nouveau_teximage_unmap(struct gl_context
*ctx
, struct gl_texture_image
*ti
)
136 struct nouveau_teximage
*nti
= to_nouveau_teximage(ti
);
137 struct nouveau_surface
*s
= &nti
->surface
;
138 struct nouveau_surface
*st
= &nti
->transfer
.surface
;
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
);
147 nti
->base
.Map
= NULL
;
152 nouveau_map_texture_image(struct gl_context
*ctx
,
153 struct gl_texture_image
*ti
,
155 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
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
);
165 /* Nouveau has no support for 3D or cubemap textures. */
169 if (!(mode
& GL_MAP_READ_BIT
) &&
170 nouveau_pushbuf_refd(context_push(ctx
), s
->bo
)) {
173 * Heuristic: use a bounce buffer to pipeline
174 * teximage transfers.
177 st
->format
= s
->format
;
181 st
->pitch
= s
->pitch
;
185 size
= get_format_blocksy(st
->format
, h
) * st
->pitch
;
186 *map
= nouveau_get_scratch(ctx
, size
,
187 &st
->bo
, &st
->offset
);
192 if (mode
& GL_MAP_READ_BIT
)
193 flags
|= NOUVEAU_BO_RD
;
194 if (mode
& GL_MAP_WRITE_BIT
)
195 flags
|= NOUVEAU_BO_WR
;
198 ret
= nouveau_bo_map(s
->bo
, flags
, client
);
203 get_format_blocksy(s
->format
, y
) * s
->pitch
+
204 get_format_blocksx(s
->format
, x
) * s
->cpp
;
208 *map
= nti
->base
.Map
+
209 get_format_blocksy(s
->format
, y
) * s
->pitch
+
210 get_format_blocksx(s
->format
, x
) * s
->cpp
;
216 nouveau_unmap_texture_image(struct gl_context
*ctx
, struct gl_texture_image
*ti
,
219 struct nouveau_teximage
*nti
= to_nouveau_teximage(ti
);
220 struct nouveau_surface
*s
= &nti
->surface
;
221 struct nouveau_surface
*st
= &nti
->transfer
.surface
;
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
);
231 nti
->base
.Map
= NULL
;
235 nouveau_choose_tex_format(struct gl_context
*ctx
, GLint internalFormat
,
236 GLenum srcFormat
, GLenum srcType
)
238 switch (internalFormat
) {
247 case GL_COMPRESSED_RGBA
:
248 return MESA_FORMAT_ARGB8888
;
250 return MESA_FORMAT_ARGB1555
;
257 case GL_COMPRESSED_RGB
:
258 return MESA_FORMAT_XRGB8888
;
263 return MESA_FORMAT_RGB565
;
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
;
282 case GL_COMPRESSED_LUMINANCE
:
283 return MESA_FORMAT_L8
;
290 case GL_COMPRESSED_ALPHA
:
291 return MESA_FORMAT_A8
;
298 return MESA_FORMAT_I8
;
302 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
303 return MESA_FORMAT_RGB_DXT1
;
305 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
306 return MESA_FORMAT_RGBA_DXT1
;
310 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
311 return MESA_FORMAT_RGBA_DXT3
;
313 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
314 return MESA_FORMAT_RGBA_DXT5
;
322 teximage_fits(struct gl_texture_object
*t
, int level
)
324 struct nouveau_surface
*s
= &to_nouveau_texture(t
)->surfaces
[level
];
325 struct gl_texture_image
*ti
= t
->Image
[0][level
];
327 if (!ti
|| !to_nouveau_teximage(ti
)->surface
.bo
)
330 if (level
== t
->BaseLevel
&& (s
->offset
& 0x7f))
333 return t
->Target
== GL_TEXTURE_RECTANGLE
||
334 (s
->bo
&& s
->format
== ti
->TexFormat
&&
335 s
->width
== ti
->Width
&& s
->height
== ti
->Height
);
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
)
343 struct gl_texture_image
*ti
= t
->Image
[0][level
];
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
;
349 if (t
->Target
== GL_TEXTURE_RECTANGLE
)
350 nouveau_surface_ref(s
, &ss
[level
]);
352 context_drv(ctx
)->surface_copy(ctx
, &ss
[level
], s
,
363 get_last_level(struct gl_texture_object
*t
)
365 struct gl_texture_image
*base
= t
->Image
[0][t
->BaseLevel
];
367 if (t
->Sampler
.MinFilter
== GL_NEAREST
||
368 t
->Sampler
.MinFilter
== GL_LINEAR
|| !base
)
371 return MIN2(t
->BaseLevel
+ base
->MaxLog2
, t
->MaxLevel
);
375 relayout_texture(struct gl_context
*ctx
, struct gl_texture_object
*t
)
377 struct gl_texture_image
*base
= t
->Image
[0][t
->BaseLevel
];
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,
389 /* Deallocate the old storage. */
390 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++)
391 nouveau_bo_ref(NULL
, &ss
[i
].bo
);
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
;
398 /* Images larger than 16B have to be aligned. */
400 offset
= align(offset
, 64);
402 ss
[i
] = (struct nouveau_surface
) {
413 width
= MAX2(1, width
/ 2);
414 height
= MAX2(1, height
/ 2);
417 /* Get new storage. */
418 size
= align(offset
, 64);
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
);
425 for (i
= t
->BaseLevel
; i
< last
; i
++)
426 nouveau_bo_ref(ss
[last
].bo
, &ss
[i
].bo
);
431 nouveau_texture_validate(struct gl_context
*ctx
, struct gl_texture_object
*t
)
433 struct nouveau_texture
*nt
= to_nouveau_texture(t
);
434 int i
, last
= get_last_level(t
);
436 if (!teximage_fits(t
, t
->BaseLevel
) ||
437 !teximage_fits(t
, last
))
441 nt
->dirty
= GL_FALSE
;
443 /* Copy the teximages to the actual miptree. */
444 for (i
= t
->BaseLevel
; i
<= last
; i
++) {
445 struct nouveau_surface
*s
= &nt
->surfaces
[i
];
447 validate_teximage(ctx
, t
, i
, 0, 0, 0,
448 s
->width
, s
->height
, 1);
451 PUSH_KICK(context_push(ctx
));
458 nouveau_texture_reallocate(struct gl_context
*ctx
, struct gl_texture_object
*t
)
460 if (!teximage_fits(t
, t
->BaseLevel
) ||
461 !teximage_fits(t
, get_last_level(t
))) {
463 relayout_texture(ctx
, t
);
464 nouveau_texture_validate(ctx
, t
);
469 get_teximage_placement(struct gl_texture_image
*ti
)
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
;
478 return NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
;
482 nouveau_teximage(struct gl_context
*ctx
, GLint dims
,
483 struct gl_texture_image
*ti
,
485 GLenum format
, GLenum type
, const GLvoid
*pixels
,
486 const struct gl_pixelstore_attrib
*packing
,
487 GLboolean compressed
)
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
);
494 GLuint depth
= compressed
? 1 : ti
->Depth
;
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
;
502 pixels
= _mesa_validate_pbo_compressed_teximage(ctx
,
504 pixels
, packing
, "glCompressedTexImage");
506 pixels
= _mesa_validate_pbo_teximage(ctx
,
507 dims
, ti
->Width
, ti
->Height
, depth
, format
, type
,
508 pixels
, packing
, "glTexImage");
511 /* Store the pixel data. */
512 nouveau_teximage_map(ctx
, ti
, GL_MAP_WRITE_BIT
,
513 0, 0, ti
->Width
, ti
->Height
);
515 ret
= _mesa_texstore(ctx
, dims
, ti
->_BaseFormat
,
519 ti
->Width
, ti
->Height
, depth
,
520 format
, type
, pixels
, packing
);
523 nouveau_teximage_unmap(ctx
, ti
);
524 _mesa_unmap_teximage_pbo(ctx
, packing
);
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. */
532 if (level
== t
->BaseLevel
) {
533 if (!teximage_fits(t
, level
))
534 relayout_texture(ctx
, t
);
535 nouveau_texture_validate(ctx
, t
);
538 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
539 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
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
)
549 nouveau_teximage(ctx
, dims
, ti
, 0, format
, type
, pixels
,
554 nouveau_compressed_teximage(struct gl_context
*ctx
, GLuint dims
,
555 struct gl_texture_image
*ti
,
556 GLsizei imageSize
, const GLvoid
*data
)
558 nouveau_teximage(ctx
, 2, ti
, imageSize
, 0, 0, data
,
559 &ctx
->Unpack
, GL_TRUE
);
563 nouveau_texsubimage(struct gl_context
*ctx
, GLint dims
,
564 struct gl_texture_image
*ti
,
565 GLint xoffset
, GLint yoffset
, GLint zoffset
,
566 GLint width
, GLint height
, GLint depth
,
568 GLenum format
, GLenum type
, const void *pixels
,
569 const struct gl_pixelstore_attrib
*packing
,
570 GLboolean compressed
)
572 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
573 struct nouveau_teximage
*nti
= to_nouveau_teximage(ti
);
577 pixels
= _mesa_validate_pbo_compressed_teximage(ctx
,
579 pixels
, packing
, "glCompressedTexSubImage");
581 pixels
= _mesa_validate_pbo_teximage(ctx
,
582 dims
, width
, height
, depth
, format
, type
,
583 pixels
, packing
, "glTexSubImage");
586 nouveau_teximage_map(ctx
, ti
, GL_MAP_WRITE_BIT
,
587 xoffset
, yoffset
, width
, height
);
589 ret
= _mesa_texstore(ctx
, dims
, ti
->_BaseFormat
, ti
->TexFormat
,
592 width
, height
, depth
,
593 format
, type
, pixels
, packing
);
596 nouveau_teximage_unmap(ctx
, ti
);
597 _mesa_unmap_teximage_pbo(ctx
, packing
);
600 if (!to_nouveau_texture(ti
->TexObject
)->dirty
)
601 validate_teximage(ctx
, ti
->TexObject
, ti
->Level
,
602 xoffset
, yoffset
, zoffset
,
603 width
, height
, depth
);
607 nouveau_texsubimage_123d(struct gl_context
*ctx
, GLuint dims
,
608 struct gl_texture_image
*ti
,
609 GLint xoffset
, GLint yoffset
, GLint zoffset
,
610 GLint width
, GLint height
, GLint depth
,
611 GLenum format
, GLenum type
, const void *pixels
,
612 const struct gl_pixelstore_attrib
*packing
)
614 nouveau_texsubimage(ctx
, dims
, ti
, xoffset
, yoffset
, zoffset
,
615 width
, height
, depth
, 0, format
, type
, pixels
,
620 nouveau_compressed_texsubimage(struct gl_context
*ctx
, GLuint dims
,
621 struct gl_texture_image
*ti
,
622 GLint xoffset
, GLint yoffset
, GLint zoffset
,
623 GLsizei width
, GLint height
, GLint depth
,
625 GLint imageSize
, const void *data
)
627 nouveau_texsubimage(ctx
, dims
, ti
, xoffset
, yoffset
, zoffset
,
628 width
, height
, depth
, imageSize
, format
, 0, data
,
629 &ctx
->Unpack
, GL_TRUE
);
633 nouveau_bind_texture(struct gl_context
*ctx
, GLenum target
,
634 struct gl_texture_object
*t
)
636 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
637 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
641 get_texbuffer_format(struct gl_renderbuffer
*rb
, GLint format
)
643 struct nouveau_surface
*s
= &to_nouveau_renderbuffer(rb
)->surface
;
647 else if (format
== __DRI_TEXTURE_FORMAT_RGBA
)
648 return MESA_FORMAT_ARGB8888
;
650 return MESA_FORMAT_XRGB8888
;
654 nouveau_set_texbuffer(__DRIcontext
*dri_ctx
,
655 GLint target
, GLint format
,
658 struct nouveau_context
*nctx
= dri_ctx
->driverPrivate
;
659 struct gl_context
*ctx
= &nctx
->base
;
660 struct gl_framebuffer
*fb
= draw
->driverPrivate
;
661 struct gl_renderbuffer
*rb
=
662 fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
663 struct gl_texture_object
*t
= _mesa_get_current_tex_object(ctx
, target
);
664 struct gl_texture_image
*ti
;
665 struct nouveau_teximage
*nti
;
666 struct nouveau_surface
*s
;
668 _mesa_lock_texture(ctx
, t
);
669 ti
= _mesa_get_tex_image(ctx
, t
, target
, 0);
670 nti
= to_nouveau_teximage(ti
);
671 s
= &to_nouveau_teximage(ti
)->surface
;
673 /* Update the texture surface with the given drawable. */
674 nouveau_update_renderbuffers(dri_ctx
, draw
);
675 nouveau_surface_ref(&to_nouveau_renderbuffer(rb
)->surface
, s
);
677 s
->format
= get_texbuffer_format(rb
, format
);
679 /* Update the image fields. */
680 _mesa_init_teximage_fields(ctx
, ti
, s
->width
, s
->height
,
681 1, 0, s
->cpp
, s
->format
);
682 nti
->base
.RowStride
= s
->pitch
/ s
->cpp
;
684 /* Try to validate it. */
685 if (!validate_teximage(ctx
, t
, 0, 0, 0, 0, s
->width
, s
->height
, 1))
686 nouveau_texture_reallocate(ctx
, t
);
688 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
689 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
691 _mesa_unlock_texture(ctx
, t
);
695 nouveau_texture_functions_init(struct dd_function_table
*functions
)
697 functions
->NewTextureObject
= nouveau_texture_new
;
698 functions
->DeleteTexture
= nouveau_texture_free
;
699 functions
->NewTextureImage
= nouveau_teximage_new
;
700 functions
->FreeTextureImageBuffer
= nouveau_teximage_free
;
701 functions
->ChooseTextureFormat
= nouveau_choose_tex_format
;
702 functions
->TexImage
= nouveau_teximage_123d
;
703 functions
->TexSubImage
= nouveau_texsubimage_123d
;
704 functions
->CompressedTexImage
= nouveau_compressed_teximage
;
705 functions
->CompressedTexSubImage
= nouveau_compressed_texsubimage
;
706 functions
->BindTexture
= nouveau_bind_texture
;
707 functions
->MapTextureImage
= nouveau_map_texture_image
;
708 functions
->UnmapTextureImage
= nouveau_unmap_texture_image
;