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_util.h"
32 #include "main/texobj.h"
33 #include "main/texstore.h"
34 #include "main/texformat.h"
35 #include "main/texcompress.h"
36 #include "main/texgetimage.h"
37 #include "main/mipmap.h"
38 #include "main/texfetch.h"
40 static struct gl_texture_object
*
41 nouveau_texture_new(GLcontext
*ctx
, GLuint name
, GLenum target
)
43 struct nouveau_texture
*nt
= CALLOC_STRUCT(nouveau_texture
);
45 _mesa_initialize_texture_object(&nt
->base
, name
, target
);
51 nouveau_texture_free(GLcontext
*ctx
, struct gl_texture_object
*t
)
53 struct nouveau_texture
*nt
= to_nouveau_texture(t
);
56 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++)
57 nouveau_surface_ref(NULL
, &nt
->surfaces
[i
]);
59 _mesa_delete_texture_object(ctx
, t
);
62 static struct gl_texture_image
*
63 nouveau_teximage_new(GLcontext
*ctx
)
65 struct nouveau_teximage
*nti
= CALLOC_STRUCT(nouveau_teximage
);
71 nouveau_teximage_free(GLcontext
*ctx
, struct gl_texture_image
*ti
)
73 struct nouveau_teximage
*nti
= to_nouveau_teximage(ti
);
75 nouveau_surface_ref(NULL
, &nti
->surface
);
79 nouveau_teximage_map(GLcontext
*ctx
, struct gl_texture_image
*ti
)
81 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
84 ret
= nouveau_bo_map(s
->bo
, NOUVEAU_BO_RDWR
);
87 ti
->Data
= s
->bo
->map
;
91 nouveau_teximage_unmap(GLcontext
*ctx
, struct gl_texture_image
*ti
)
93 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
95 nouveau_bo_unmap(s
->bo
);
100 nouveau_choose_tex_format(GLcontext
*ctx
, GLint internalFormat
,
101 GLenum srcFormat
, GLenum srcType
)
103 switch (internalFormat
) {
115 return MESA_FORMAT_ARGB8888
;
117 return MESA_FORMAT_ARGB1555
;
120 return MESA_FORMAT_ARGB4444
;
126 return MESA_FORMAT_RGB565
;
133 return MESA_FORMAT_A8
;
141 return MESA_FORMAT_L8
;
144 case GL_LUMINANCE_ALPHA
:
145 case GL_LUMINANCE4_ALPHA4
:
146 case GL_LUMINANCE6_ALPHA2
:
147 case GL_LUMINANCE12_ALPHA4
:
148 case GL_LUMINANCE12_ALPHA12
:
149 case GL_LUMINANCE16_ALPHA16
:
150 case GL_LUMINANCE8_ALPHA8
:
151 return MESA_FORMAT_ARGB8888
;
158 return MESA_FORMAT_ARGB8888
;
161 case GL_COLOR_INDEX1_EXT
:
162 case GL_COLOR_INDEX2_EXT
:
163 case GL_COLOR_INDEX4_EXT
:
164 case GL_COLOR_INDEX12_EXT
:
165 case GL_COLOR_INDEX16_EXT
:
166 case GL_COLOR_INDEX8_EXT
:
167 return MESA_FORMAT_CI8
;
175 nouveau_teximage(GLcontext
*ctx
, GLint dims
, GLenum target
, GLint level
,
176 GLint internalFormat
,
177 GLint width
, GLint height
, GLint depth
, GLint border
,
178 GLenum format
, GLenum type
, const GLvoid
*pixels
,
179 const struct gl_pixelstore_attrib
*packing
,
180 struct gl_texture_object
*t
,
181 struct gl_texture_image
*ti
)
183 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
184 unsigned bo_flags
= NOUVEAU_BO_GART
| NOUVEAU_BO_RDWR
| NOUVEAU_BO_MAP
;
187 /* Allocate a new bo for the image. */
188 nouveau_surface_alloc(ctx
, s
, LINEAR
, bo_flags
, ti
->TexFormat
,
190 ti
->RowStride
= s
->pitch
/ s
->cpp
;
192 pixels
= _mesa_validate_pbo_teximage(ctx
, dims
, width
, height
, depth
,
193 format
, type
, pixels
, packing
,
198 /* Store the pixel data. */
199 nouveau_teximage_map(ctx
, ti
);
201 ret
= _mesa_texstore(ctx
, dims
, ti
->_BaseFormat
,
202 ti
->TexFormat
, ti
->Data
,
205 width
, height
, depth
,
206 format
, type
, pixels
, packing
);
209 nouveau_teximage_unmap(ctx
, ti
);
210 _mesa_unmap_teximage_pbo(ctx
, packing
);
212 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
213 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
218 nouveau_teximage_1d(GLcontext
*ctx
, GLenum target
, GLint level
,
219 GLint internalFormat
,
220 GLint width
, GLint border
,
221 GLenum format
, GLenum type
, const GLvoid
*pixels
,
222 const struct gl_pixelstore_attrib
*packing
,
223 struct gl_texture_object
*t
,
224 struct gl_texture_image
*ti
)
226 nouveau_teximage(ctx
, 1, target
, level
, internalFormat
,
227 width
, 1, 1, border
, format
, type
, pixels
,
232 nouveau_teximage_2d(GLcontext
*ctx
, GLenum target
, GLint level
,
233 GLint internalFormat
,
234 GLint width
, GLint height
, GLint border
,
235 GLenum format
, GLenum type
, const GLvoid
*pixels
,
236 const struct gl_pixelstore_attrib
*packing
,
237 struct gl_texture_object
*t
,
238 struct gl_texture_image
*ti
)
240 nouveau_teximage(ctx
, 2, target
, level
, internalFormat
,
241 width
, height
, 1, border
, format
, type
, pixels
,
246 nouveau_teximage_3d(GLcontext
*ctx
, GLenum target
, GLint level
,
247 GLint internalFormat
,
248 GLint width
, GLint height
, GLint depth
, GLint border
,
249 GLenum format
, GLenum type
, const GLvoid
*pixels
,
250 const struct gl_pixelstore_attrib
*packing
,
251 struct gl_texture_object
*t
,
252 struct gl_texture_image
*ti
)
254 nouveau_teximage(ctx
, 3, target
, level
, internalFormat
,
255 width
, height
, depth
, border
, format
, type
, pixels
,
260 nouveau_texsubimage_3d(GLcontext
*ctx
, GLenum target
, GLint level
,
261 GLint xoffset
, GLint yoffset
, GLint zoffset
,
262 GLint width
, GLint height
, GLint depth
,
263 GLenum format
, GLenum type
, const void *pixels
,
264 const struct gl_pixelstore_attrib
*packing
,
265 struct gl_texture_object
*t
,
266 struct gl_texture_image
*ti
)
268 nouveau_teximage_map(ctx
, ti
);
269 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
270 width
, height
, depth
, format
, type
, pixels
,
272 nouveau_teximage_unmap(ctx
, ti
);
274 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
279 nouveau_texsubimage_2d(GLcontext
*ctx
, GLenum target
, GLint level
,
280 GLint xoffset
, GLint yoffset
,
281 GLint width
, GLint height
,
282 GLenum format
, GLenum type
, const void *pixels
,
283 const struct gl_pixelstore_attrib
*packing
,
284 struct gl_texture_object
*t
,
285 struct gl_texture_image
*ti
)
287 nouveau_teximage_map(ctx
, ti
);
288 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
,
289 width
, height
, format
, type
, pixels
,
291 nouveau_teximage_unmap(ctx
, ti
);
293 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
298 nouveau_texsubimage_1d(GLcontext
*ctx
, GLenum target
, GLint level
,
299 GLint xoffset
, GLint width
,
300 GLenum format
, GLenum type
, const void *pixels
,
301 const struct gl_pixelstore_attrib
*packing
,
302 struct gl_texture_object
*t
,
303 struct gl_texture_image
*ti
)
305 nouveau_teximage_map(ctx
, ti
);
306 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
,
307 width
, format
, type
, pixels
,
309 nouveau_teximage_unmap(ctx
, ti
);
311 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
316 nouveau_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
317 GLenum format
, GLenum type
, GLvoid
*pixels
,
318 struct gl_texture_object
*t
,
319 struct gl_texture_image
*ti
)
321 nouveau_teximage_map(ctx
, ti
);
322 _mesa_get_teximage(ctx
, target
, level
, format
, type
, pixels
,
324 nouveau_teximage_unmap(ctx
, ti
);
328 nouveau_bind_texture(GLcontext
*ctx
, GLenum target
,
329 struct gl_texture_object
*t
)
331 context_dirty_i(ctx
, TEX_OBJ
, ctx
->Texture
.CurrentUnit
);
332 context_dirty_i(ctx
, TEX_ENV
, ctx
->Texture
.CurrentUnit
);
336 nouveau_texture_map(GLcontext
*ctx
, struct gl_texture_object
*t
)
340 for (i
= t
->BaseLevel
; i
< t
->_MaxLevel
; i
++) {
342 nouveau_teximage_map(ctx
, t
->Image
[0][i
]);
347 nouveau_texture_unmap(GLcontext
*ctx
, struct gl_texture_object
*t
)
351 for (i
= t
->BaseLevel
; i
< t
->_MaxLevel
; i
++) {
353 nouveau_teximage_unmap(ctx
, t
->Image
[0][i
]);
358 relayout_miptree(GLcontext
*ctx
, struct gl_texture_object
*t
)
360 struct nouveau_surface
*ss
= to_nouveau_texture(t
)->surfaces
;
361 unsigned last_level
, offset
= 0;
365 if (t
->MinFilter
== GL_NEAREST
||
366 t
->MinFilter
== GL_LINEAR
)
367 last_level
= t
->BaseLevel
;
369 last_level
= t
->_MaxLevel
;
371 /* Deallocate the old storage. */
372 for (i
= 0; i
< MAX_TEXTURE_LEVELS
; i
++)
373 nouveau_bo_ref(NULL
, &ss
[i
].bo
);
375 /* Relayout the mipmap tree. */
376 for (i
= t
->BaseLevel
; i
<= last_level
; i
++) {
377 struct nouveau_surface
*s
=
378 &to_nouveau_teximage(t
->Image
[0][i
])->surface
;
380 size
= s
->width
* s
->height
* s
->cpp
;
382 /* Images larger than 16B have to be aligned. */
384 offset
= align(offset
, 64);
386 ss
[i
] = (struct nouveau_surface
) {
393 .pitch
= s
->width
* s
->cpp
,
399 /* Get new storage. */
400 size
= align(offset
, 64);
402 ret
= nouveau_bo_new(context_dev(ctx
),
403 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
,
404 0, size
, &ss
[last_level
].bo
);
407 for (i
= t
->BaseLevel
; i
< last_level
; i
++)
408 nouveau_bo_ref(ss
[last_level
].bo
, &ss
[i
].bo
);
412 nouveau_texture_validate(GLcontext
*ctx
, struct gl_texture_object
*t
)
414 struct nouveau_texture
*nt
= to_nouveau_texture(t
);
420 nt
->dirty
= GL_FALSE
;
422 relayout_miptree(ctx
, t
);
424 /* Copy the teximages to the actual swizzled miptree. */
425 for (i
= t
->BaseLevel
; i
< MAX_TEXTURE_LEVELS
; i
++) {
426 struct gl_texture_image
*ti
= t
->Image
[0][i
];
427 struct nouveau_surface
*s
= &to_nouveau_teximage(ti
)->surface
;
429 if (!nt
->surfaces
[i
].bo
)
432 context_drv(ctx
)->surface_copy(ctx
, &nt
->surfaces
[i
], s
,
434 s
->width
, s
->height
);
439 nouveau_texture_functions_init(struct dd_function_table
*functions
)
441 functions
->NewTextureObject
= nouveau_texture_new
;
442 functions
->DeleteTexture
= nouveau_texture_free
;
443 functions
->NewTextureImage
= nouveau_teximage_new
;
444 functions
->FreeTexImageData
= nouveau_teximage_free
;
445 functions
->ChooseTextureFormat
= nouveau_choose_tex_format
;
446 functions
->TexImage1D
= nouveau_teximage_1d
;
447 functions
->TexImage2D
= nouveau_teximage_2d
;
448 functions
->TexImage3D
= nouveau_teximage_3d
;
449 functions
->TexSubImage1D
= nouveau_texsubimage_1d
;
450 functions
->TexSubImage2D
= nouveau_texsubimage_2d
;
451 functions
->TexSubImage3D
= nouveau_texsubimage_3d
;
452 functions
->GetTexImage
= nouveau_get_teximage
;
453 functions
->BindTexture
= nouveau_bind_texture
;
454 functions
->MapTexture
= nouveau_texture_map
;
455 functions
->UnmapTexture
= nouveau_texture_unmap
;