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"
33 #include "main/texobj.h"
34 #include "main/texstore.h"
35 #include "main/texformat.h"
36 #include "main/texcompress.h"
37 #include "main/texgetimage.h"
38 #include "main/mipmap.h"
39 #include "main/texfetch.h"
40 #include "main/teximage.h"
41 #include "drivers/common/meta.h"
43 static struct gl_texture_object
*
44 nouveau_texture_new(struct gl_context
*ctx
, GLuint name
, GLenum target
)
46 struct nouveau_texture
*nt
= CALLOC_STRUCT(nouveau_texture
);
48 _mesa_initialize_texture_object(&nt
->base
, name
, target
);
54 nouveau_texture_free(struct gl_context
*ctx
, struct gl_texture_object
*t
)
56 struct nouveau_texture
*nt
= to_nouveau_texture(t
);
59 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++)
60 nouveau_surface_ref(NULL
, &nt
->surfaces
[i
]);
62 _mesa_delete_texture_object(ctx
, t
);
65 static struct gl_texture_image
*
66 nouveau_teximage_new(struct gl_context
*ctx
)
68 struct nouveau_teximage
*nti
= CALLOC_STRUCT(nouveau_teximage
);
74 nouveau_teximage_free(struct gl_context
*ctx
, struct gl_texture_image
*ti
)
76 struct nouveau_teximage
*nti
= to_nouveau_teximage(ti
);
78 nouveau_surface_ref(NULL
, &nti
->surface
);
82 nouveau_teximage_map(struct gl_context
*ctx
, struct gl_texture_image
*ti
)
84 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
88 ret
= nouveau_bo_map(s
->bo
, NOUVEAU_BO_RDWR
);
91 ti
->Data
= s
->bo
->map
;
96 nouveau_teximage_unmap(struct gl_context
*ctx
, struct gl_texture_image
*ti
)
98 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
101 nouveau_bo_unmap(s
->bo
);
106 nouveau_choose_tex_format(struct gl_context
*ctx
, GLint internalFormat
,
107 GLenum srcFormat
, GLenum srcType
)
109 switch (internalFormat
) {
118 case GL_COMPRESSED_RGBA
:
119 return MESA_FORMAT_ARGB8888
;
121 return MESA_FORMAT_ARGB1555
;
128 case GL_COMPRESSED_RGB
:
129 return MESA_FORMAT_XRGB8888
;
134 return MESA_FORMAT_RGB565
;
137 case GL_LUMINANCE_ALPHA
:
138 case GL_LUMINANCE4_ALPHA4
:
139 case GL_LUMINANCE6_ALPHA2
:
140 case GL_LUMINANCE12_ALPHA4
:
141 case GL_LUMINANCE12_ALPHA12
:
142 case GL_LUMINANCE16_ALPHA16
:
143 case GL_LUMINANCE8_ALPHA8
:
144 case GL_COMPRESSED_LUMINANCE_ALPHA
:
145 return MESA_FORMAT_ARGB8888
;
153 case GL_COMPRESSED_LUMINANCE
:
154 return MESA_FORMAT_L8
;
161 case GL_COMPRESSED_ALPHA
:
162 return MESA_FORMAT_A8
;
169 return MESA_FORMAT_I8
;
172 case GL_COLOR_INDEX1_EXT
:
173 case GL_COLOR_INDEX2_EXT
:
174 case GL_COLOR_INDEX4_EXT
:
175 case GL_COLOR_INDEX12_EXT
:
176 case GL_COLOR_INDEX16_EXT
:
177 case GL_COLOR_INDEX8_EXT
:
178 return MESA_FORMAT_CI8
;
186 teximage_fits(struct gl_texture_object
*t
, int level
)
188 struct nouveau_surface
*s
= &to_nouveau_texture(t
)->surfaces
[level
];
189 struct gl_texture_image
*ti
= t
->Image
[0][level
];
191 if (!ti
|| !to_nouveau_teximage(ti
)->surface
.bo
)
194 if (level
== t
->BaseLevel
&& (s
->offset
& 0x7f))
197 return t
->Target
== GL_TEXTURE_RECTANGLE
||
198 (s
->bo
&& s
->format
== ti
->TexFormat
&&
199 s
->width
== ti
->Width
&& s
->height
== ti
->Height
);
203 validate_teximage(struct gl_context
*ctx
, struct gl_texture_object
*t
,
204 int level
, int x
, int y
, int z
,
205 int width
, int height
, int depth
)
207 struct gl_texture_image
*ti
= t
->Image
[0][level
];
209 if (teximage_fits(t
, level
)) {
210 struct nouveau_surface
*ss
= to_nouveau_texture(t
)->surfaces
;
211 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
213 if (t
->Target
== GL_TEXTURE_RECTANGLE
)
214 nouveau_surface_ref(s
, &ss
[level
]);
216 context_drv(ctx
)->surface_copy(ctx
, &ss
[level
], s
,
227 get_last_level(struct gl_texture_object
*t
)
229 struct gl_texture_image
*base
= t
->Image
[0][t
->BaseLevel
];
231 if (t
->MinFilter
== GL_NEAREST
||
232 t
->MinFilter
== GL_LINEAR
|| !base
)
235 return MIN2(t
->BaseLevel
+ base
->MaxLog2
, t
->MaxLevel
);
239 relayout_texture(struct gl_context
*ctx
, struct gl_texture_object
*t
)
241 struct gl_texture_image
*base
= t
->Image
[0][t
->BaseLevel
];
243 if (base
&& t
->Target
!= GL_TEXTURE_RECTANGLE
) {
244 struct nouveau_surface
*ss
= to_nouveau_texture(t
)->surfaces
;
245 struct nouveau_surface
*s
= &to_nouveau_teximage(base
)->surface
;
246 int i
, ret
, last
= get_last_level(t
);
247 unsigned size
, offset
= 0,
251 /* Deallocate the old storage. */
252 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++)
253 nouveau_bo_ref(NULL
, &ss
[i
].bo
);
255 /* Relayout the mipmap tree. */
256 for (i
= t
->BaseLevel
; i
<= last
; i
++) {
257 size
= width
* height
* s
->cpp
;
259 /* Images larger than 16B have to be aligned. */
261 offset
= align(offset
, 64);
263 ss
[i
] = (struct nouveau_surface
) {
270 .pitch
= width
* s
->cpp
,
274 width
= MAX2(1, width
/ 2);
275 height
= MAX2(1, height
/ 2);
278 /* Get new storage. */
279 size
= align(offset
, 64);
281 ret
= nouveau_bo_new(context_dev(ctx
), NOUVEAU_BO_MAP
|
282 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
,
283 0, size
, &ss
[last
].bo
);
286 for (i
= t
->BaseLevel
; i
< last
; i
++)
287 nouveau_bo_ref(ss
[last
].bo
, &ss
[i
].bo
);
292 nouveau_texture_validate(struct gl_context
*ctx
, struct gl_texture_object
*t
)
294 struct nouveau_texture
*nt
= to_nouveau_texture(t
);
295 int i
, last
= get_last_level(t
);
297 if (!teximage_fits(t
, t
->BaseLevel
) ||
298 !teximage_fits(t
, last
))
302 nt
->dirty
= GL_FALSE
;
304 /* Copy the teximages to the actual miptree. */
305 for (i
= t
->BaseLevel
; i
<= last
; i
++) {
306 struct nouveau_surface
*s
= &nt
->surfaces
[i
];
308 validate_teximage(ctx
, t
, i
, 0, 0, 0,
309 s
->width
, s
->height
, 1);
312 FIRE_RING(context_chan(ctx
));
319 nouveau_texture_reallocate(struct gl_context
*ctx
, struct gl_texture_object
*t
)
321 if (!teximage_fits(t
, t
->BaseLevel
) ||
322 !teximage_fits(t
, get_last_level(t
))) {
324 relayout_texture(ctx
, t
);
325 nouveau_texture_validate(ctx
, t
);
330 get_teximage_placement(struct gl_texture_image
*ti
)
332 if (ti
->TexFormat
== MESA_FORMAT_A8
||
333 ti
->TexFormat
== MESA_FORMAT_L8
||
334 ti
->TexFormat
== MESA_FORMAT_I8
)
335 /* 1 cpp formats will have to be swizzled by the CPU,
336 * so leave them in system RAM for now. */
337 return NOUVEAU_BO_MAP
;
339 return NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
;
343 nouveau_teximage(struct gl_context
*ctx
, GLint dims
, GLenum target
, GLint level
,
344 GLint internalFormat
,
345 GLint width
, GLint height
, GLint depth
, GLint border
,
346 GLenum format
, GLenum type
, const GLvoid
*pixels
,
347 const struct gl_pixelstore_attrib
*packing
,
348 struct gl_texture_object
*t
,
349 struct gl_texture_image
*ti
)
351 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
354 /* Allocate a new bo for the image. */
355 nouveau_surface_alloc(ctx
, s
, LINEAR
, get_teximage_placement(ti
),
356 ti
->TexFormat
, width
, height
);
357 ti
->RowStride
= s
->pitch
/ s
->cpp
;
359 pixels
= _mesa_validate_pbo_teximage(ctx
, dims
, width
, height
, depth
,
360 format
, type
, pixels
, packing
,
363 /* Store the pixel data. */
364 nouveau_teximage_map(ctx
, ti
);
366 ret
= _mesa_texstore(ctx
, dims
, ti
->_BaseFormat
,
367 ti
->TexFormat
, ti
->Data
,
370 width
, height
, depth
,
371 format
, type
, pixels
, packing
);
374 nouveau_teximage_unmap(ctx
, ti
);
375 _mesa_unmap_teximage_pbo(ctx
, packing
);
377 if (!validate_teximage(ctx
, t
, level
, 0, 0, 0,
378 width
, height
, depth
))
379 /* It doesn't fit, mark it as dirty. */
383 if (level
== t
->BaseLevel
) {
384 if (!teximage_fits(t
, level
))
385 relayout_texture(ctx
, t
);
386 nouveau_texture_validate(ctx
, t
);
389 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
390 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
394 nouveau_teximage_1d(struct gl_context
*ctx
, GLenum target
, GLint level
,
395 GLint internalFormat
,
396 GLint width
, GLint border
,
397 GLenum format
, GLenum type
, const GLvoid
*pixels
,
398 const struct gl_pixelstore_attrib
*packing
,
399 struct gl_texture_object
*t
,
400 struct gl_texture_image
*ti
)
402 nouveau_teximage(ctx
, 1, target
, level
, internalFormat
,
403 width
, 1, 1, border
, format
, type
, pixels
,
408 nouveau_teximage_2d(struct gl_context
*ctx
, GLenum target
, GLint level
,
409 GLint internalFormat
,
410 GLint width
, GLint height
, GLint border
,
411 GLenum format
, GLenum type
, const GLvoid
*pixels
,
412 const struct gl_pixelstore_attrib
*packing
,
413 struct gl_texture_object
*t
,
414 struct gl_texture_image
*ti
)
416 nouveau_teximage(ctx
, 2, target
, level
, internalFormat
,
417 width
, height
, 1, border
, format
, type
, pixels
,
422 nouveau_teximage_3d(struct gl_context
*ctx
, GLenum target
, GLint level
,
423 GLint internalFormat
,
424 GLint width
, GLint height
, GLint depth
, GLint border
,
425 GLenum format
, GLenum type
, const GLvoid
*pixels
,
426 const struct gl_pixelstore_attrib
*packing
,
427 struct gl_texture_object
*t
,
428 struct gl_texture_image
*ti
)
430 nouveau_teximage(ctx
, 3, target
, level
, internalFormat
,
431 width
, height
, depth
, border
, format
, type
, pixels
,
436 nouveau_texsubimage(struct gl_context
*ctx
, GLint dims
, GLenum target
, GLint level
,
437 GLint xoffset
, GLint yoffset
, GLint zoffset
,
438 GLint width
, GLint height
, GLint depth
,
439 GLenum format
, GLenum type
, const void *pixels
,
440 const struct gl_pixelstore_attrib
*packing
,
441 struct gl_texture_object
*t
,
442 struct gl_texture_image
*ti
)
444 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
447 pixels
= _mesa_validate_pbo_teximage(ctx
, dims
, width
, height
, depth
,
448 format
, type
, pixels
, packing
,
451 nouveau_teximage_map(ctx
, ti
);
453 ret
= _mesa_texstore(ctx
, 3, ti
->_BaseFormat
, ti
->TexFormat
,
454 ti
->Data
, xoffset
, yoffset
, zoffset
,
455 s
->pitch
, ti
->ImageOffsets
,
456 width
, height
, depth
, format
, type
,
460 nouveau_teximage_unmap(ctx
, ti
);
461 _mesa_unmap_teximage_pbo(ctx
, packing
);
464 if (!to_nouveau_texture(t
)->dirty
)
465 validate_teximage(ctx
, t
, level
, xoffset
, yoffset
, zoffset
,
466 width
, height
, depth
);
470 nouveau_texsubimage_3d(struct gl_context
*ctx
, GLenum target
, GLint level
,
471 GLint xoffset
, GLint yoffset
, GLint zoffset
,
472 GLint width
, GLint height
, GLint depth
,
473 GLenum format
, GLenum type
, const void *pixels
,
474 const struct gl_pixelstore_attrib
*packing
,
475 struct gl_texture_object
*t
,
476 struct gl_texture_image
*ti
)
478 nouveau_texsubimage(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
479 width
, height
, depth
, format
, type
, pixels
,
484 nouveau_texsubimage_2d(struct gl_context
*ctx
, GLenum target
, GLint level
,
485 GLint xoffset
, GLint yoffset
,
486 GLint width
, GLint height
,
487 GLenum format
, GLenum type
, const void *pixels
,
488 const struct gl_pixelstore_attrib
*packing
,
489 struct gl_texture_object
*t
,
490 struct gl_texture_image
*ti
)
492 nouveau_texsubimage(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
493 width
, height
, 1, format
, type
, pixels
,
498 nouveau_texsubimage_1d(struct gl_context
*ctx
, GLenum target
, GLint level
,
499 GLint xoffset
, GLint width
,
500 GLenum format
, GLenum type
, const void *pixels
,
501 const struct gl_pixelstore_attrib
*packing
,
502 struct gl_texture_object
*t
,
503 struct gl_texture_image
*ti
)
505 nouveau_texsubimage(ctx
, 1, target
, level
, xoffset
, 0, 0,
506 width
, 1, 1, format
, type
, pixels
,
511 nouveau_get_teximage(struct gl_context
*ctx
, GLenum target
, GLint level
,
512 GLenum format
, GLenum type
, GLvoid
*pixels
,
513 struct gl_texture_object
*t
,
514 struct gl_texture_image
*ti
)
516 nouveau_teximage_map(ctx
, ti
);
517 _mesa_get_teximage(ctx
, target
, level
, format
, type
, pixels
,
519 nouveau_teximage_unmap(ctx
, ti
);
523 nouveau_bind_texture(struct gl_context
*ctx
, GLenum target
,
524 struct gl_texture_object
*t
)
526 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
527 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
531 get_texbuffer_format(struct gl_renderbuffer
*rb
, GLint format
)
533 struct nouveau_surface
*s
= &to_nouveau_renderbuffer(rb
)->surface
;
537 else if (format
== __DRI_TEXTURE_FORMAT_RGBA
)
538 return MESA_FORMAT_ARGB8888
;
540 return MESA_FORMAT_XRGB8888
;
544 nouveau_set_texbuffer(__DRIcontext
*dri_ctx
,
545 GLint target
, GLint format
,
548 struct nouveau_context
*nctx
= dri_ctx
->driverPrivate
;
549 struct gl_context
*ctx
= &nctx
->base
;
550 struct gl_framebuffer
*fb
= draw
->driverPrivate
;
551 struct gl_renderbuffer
*rb
=
552 fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
553 struct gl_texture_object
*t
= _mesa_get_current_tex_object(ctx
, target
);
554 struct gl_texture_image
*ti
;
555 struct nouveau_surface
*s
;
557 _mesa_lock_texture(ctx
, t
);
558 ti
= _mesa_get_tex_image(ctx
, t
, target
, 0);
559 s
= &to_nouveau_teximage(ti
)->surface
;
561 /* Update the texture surface with the given drawable. */
562 nouveau_update_renderbuffers(dri_ctx
, draw
);
563 nouveau_surface_ref(&to_nouveau_renderbuffer(rb
)->surface
, s
);
565 /* Update the image fields. */
566 _mesa_init_teximage_fields(ctx
, target
, ti
, s
->width
, s
->height
,
568 ti
->RowStride
= s
->pitch
/ s
->cpp
;
569 ti
->TexFormat
= s
->format
= get_texbuffer_format(rb
, format
);
571 /* Try to validate it. */
572 if (!validate_teximage(ctx
, t
, 0, 0, 0, 0, s
->width
, s
->height
, 1))
573 nouveau_texture_reallocate(ctx
, t
);
575 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
576 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
578 _mesa_unlock_texture(ctx
, t
);
582 nouveau_texture_map(struct gl_context
*ctx
, struct gl_texture_object
*t
)
586 for (i
= t
->BaseLevel
; i
< t
->_MaxLevel
; i
++) {
588 nouveau_teximage_map(ctx
, t
->Image
[0][i
]);
593 nouveau_texture_unmap(struct gl_context
*ctx
, struct gl_texture_object
*t
)
597 for (i
= t
->BaseLevel
; i
< t
->_MaxLevel
; i
++) {
599 nouveau_teximage_unmap(ctx
, t
->Image
[0][i
]);
604 store_mipmap(struct gl_context
*ctx
, GLenum target
, int first
, int last
,
605 struct gl_texture_object
*t
)
607 struct gl_pixelstore_attrib packing
= {
608 .BufferObj
= ctx
->Shared
->NullBufferObj
,
611 GLenum format
= t
->Image
[0][t
->BaseLevel
]->TexFormat
;
612 unsigned base_format
, type
, comps
;
615 base_format
= _mesa_get_format_base_format(format
);
616 _mesa_format_to_type_and_comps(format
, &type
, &comps
);
618 for (i
= first
; i
<= last
; i
++) {
619 struct gl_texture_image
*ti
= t
->Image
[0][i
];
620 void *data
= ti
->Data
;
622 nouveau_teximage(ctx
, 3, target
, i
, ti
->InternalFormat
,
623 ti
->Width
, ti
->Height
, ti
->Depth
,
624 ti
->Border
, base_format
, type
, data
,
627 _mesa_free_texmemory(data
);
632 nouveau_generate_mipmap(struct gl_context
*ctx
, GLenum target
,
633 struct gl_texture_object
*t
)
635 if (_mesa_meta_check_generate_mipmap_fallback(ctx
, target
, t
)) {
636 struct gl_texture_image
*base
= t
->Image
[0][t
->BaseLevel
];
638 nouveau_teximage_map(ctx
, base
);
639 _mesa_generate_mipmap(ctx
, target
, t
);
640 nouveau_teximage_unmap(ctx
, base
);
642 store_mipmap(ctx
, target
, t
->BaseLevel
+ 1,
643 get_last_level(t
), t
);
646 _mesa_meta_GenerateMipmap(ctx
, target
, t
);
651 nouveau_texture_functions_init(struct dd_function_table
*functions
)
653 functions
->NewTextureObject
= nouveau_texture_new
;
654 functions
->DeleteTexture
= nouveau_texture_free
;
655 functions
->NewTextureImage
= nouveau_teximage_new
;
656 functions
->FreeTexImageData
= nouveau_teximage_free
;
657 functions
->ChooseTextureFormat
= nouveau_choose_tex_format
;
658 functions
->TexImage1D
= nouveau_teximage_1d
;
659 functions
->TexImage2D
= nouveau_teximage_2d
;
660 functions
->TexImage3D
= nouveau_teximage_3d
;
661 functions
->TexSubImage1D
= nouveau_texsubimage_1d
;
662 functions
->TexSubImage2D
= nouveau_texsubimage_2d
;
663 functions
->TexSubImage3D
= nouveau_texsubimage_3d
;
664 functions
->GetTexImage
= nouveau_get_teximage
;
665 functions
->BindTexture
= nouveau_bind_texture
;
666 functions
->MapTexture
= nouveau_texture_map
;
667 functions
->UnmapTexture
= nouveau_texture_unmap
;
668 functions
->GenerateMipmap
= nouveau_generate_mipmap
;