dri/nouveau: Try to validate textures earlier.
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_texture.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
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:
12 *
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.
16 *
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.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29 #include "nouveau_texture.h"
30 #include "nouveau_util.h"
31
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"
39
40 static struct gl_texture_object *
41 nouveau_texture_new(GLcontext *ctx, GLuint name, GLenum target)
42 {
43 struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture);
44
45 _mesa_initialize_texture_object(&nt->base, name, target);
46
47 return &nt->base;
48 }
49
50 static void
51 nouveau_texture_free(GLcontext *ctx, struct gl_texture_object *t)
52 {
53 struct nouveau_texture *nt = to_nouveau_texture(t);
54 int i;
55
56 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
57 nouveau_surface_ref(NULL, &nt->surfaces[i]);
58
59 _mesa_delete_texture_object(ctx, t);
60 }
61
62 static struct gl_texture_image *
63 nouveau_teximage_new(GLcontext *ctx)
64 {
65 struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
66
67 return &nti->base;
68 }
69
70 static void
71 nouveau_teximage_free(GLcontext *ctx, struct gl_texture_image *ti)
72 {
73 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
74
75 nouveau_surface_ref(NULL, &nti->surface);
76 }
77
78 static void
79 nouveau_teximage_map(GLcontext *ctx, struct gl_texture_image *ti)
80 {
81 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
82 int ret;
83
84 ret = nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR);
85 assert(!ret);
86
87 ti->Data = s->bo->map;
88 }
89
90 static void
91 nouveau_teximage_unmap(GLcontext *ctx, struct gl_texture_image *ti)
92 {
93 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
94
95 nouveau_bo_unmap(s->bo);
96 ti->Data = NULL;
97 }
98
99 static gl_format
100 nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat,
101 GLenum srcFormat, GLenum srcType)
102 {
103 switch (internalFormat) {
104 case 4:
105 case GL_RGBA:
106 case GL_RGB10_A2:
107 case GL_RGBA12:
108 case GL_RGBA16:
109 case GL_RGBA8:
110 case GL_RGB:
111 case GL_RGB8:
112 case GL_RGB10:
113 case GL_RGB12:
114 case GL_RGB16:
115 return MESA_FORMAT_ARGB8888;
116 case GL_RGB5_A1:
117 return MESA_FORMAT_ARGB1555;
118 case GL_RGBA2:
119 case GL_RGBA4:
120 return MESA_FORMAT_ARGB4444;
121
122 case 3:
123 case GL_R3_G3_B2:
124 case GL_RGB4:
125 case GL_RGB5:
126 return MESA_FORMAT_RGB565;
127
128 case GL_ALPHA:
129 case GL_ALPHA4:
130 case GL_ALPHA12:
131 case GL_ALPHA16:
132 case GL_ALPHA8:
133 return MESA_FORMAT_A8;
134
135 case 1:
136 case GL_LUMINANCE:
137 case GL_LUMINANCE4:
138 case GL_LUMINANCE12:
139 case GL_LUMINANCE16:
140 case GL_LUMINANCE8:
141 return MESA_FORMAT_L8;
142
143 case 2:
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;
152
153 case GL_INTENSITY:
154 case GL_INTENSITY4:
155 case GL_INTENSITY12:
156 case GL_INTENSITY16:
157 case GL_INTENSITY8:
158 return MESA_FORMAT_ARGB8888;
159
160 case GL_COLOR_INDEX:
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;
168
169 default:
170 assert(0);
171 }
172 }
173
174 static GLboolean
175 teximage_fits(struct gl_texture_object *t, int level,
176 struct gl_texture_image *ti)
177 {
178 struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
179
180 return s->bo && s->width == ti->Width &&
181 s->height == ti->Height &&
182 s->format == ti->TexFormat;
183 }
184
185 static GLboolean
186 validate_teximage(GLcontext *ctx, struct gl_texture_object *t,
187 int level, int x, int y, int z,
188 int width, int height, int depth)
189 {
190 struct gl_texture_image *ti = t->Image[0][level];
191
192 if (ti && teximage_fits(t, level, ti)) {
193 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
194 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
195
196 context_drv(ctx)->surface_copy(ctx, &ss[level], s,
197 x, y, x, y,
198 width, height);
199
200 return GL_TRUE;
201 }
202
203 return GL_FALSE;
204 }
205
206 static int
207 get_last_level(struct gl_texture_object *t)
208 {
209 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
210
211 if (t->MinFilter == GL_NEAREST ||
212 t->MinFilter == GL_LINEAR || !base)
213 return t->BaseLevel;
214 else
215 return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel);
216 }
217
218 static void
219 relayout_texture(GLcontext *ctx, struct gl_texture_object *t)
220 {
221 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
222
223 if (base) {
224 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
225 struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
226 int i, ret, last = get_last_level(t);
227 unsigned size, offset = 0,
228 width = s->width,
229 height = s->height;
230
231 /* Deallocate the old storage. */
232 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
233 nouveau_bo_ref(NULL, &ss[i].bo);
234
235 /* Relayout the mipmap tree. */
236 for (i = t->BaseLevel; i <= last; i++) {
237 size = width * height * s->cpp;
238
239 /* Images larger than 16B have to be aligned. */
240 if (size > 16)
241 offset = align(offset, 64);
242
243 ss[i] = (struct nouveau_surface) {
244 .offset = offset,
245 .layout = SWIZZLED,
246 .format = s->format,
247 .width = width,
248 .height = height,
249 .cpp = s->cpp,
250 .pitch = width * s->cpp,
251 };
252
253 offset += size;
254 width = MAX2(1, width / 2);
255 height = MAX2(1, height / 2);
256 }
257
258 /* Get new storage. */
259 size = align(offset, 64);
260
261 ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
262 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
263 0, size, &ss[last].bo);
264 assert(!ret);
265
266 for (i = t->BaseLevel; i < last; i++)
267 nouveau_bo_ref(ss[last].bo, &ss[i].bo);
268 }
269 }
270
271 GLboolean
272 nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t)
273 {
274 struct nouveau_texture *nt = to_nouveau_texture(t);
275 int i, last = get_last_level(t);
276
277 if (!nt->surfaces[last].bo)
278 return GL_FALSE;
279
280 if (nt->dirty) {
281 nt->dirty = GL_FALSE;
282
283 /* Copy the teximages to the actual miptree. */
284 for (i = t->BaseLevel; i <= last; i++) {
285 struct nouveau_surface *s = &nt->surfaces[i];
286
287 validate_teximage(ctx, t, i, 0, 0, 0,
288 s->width, s->height, 1);
289 }
290 }
291
292 return GL_TRUE;
293 }
294
295 void
296 nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t)
297 {
298 texture_dirty(t);
299 relayout_texture(ctx, t);
300 nouveau_texture_validate(ctx, t);
301 }
302
303 static unsigned
304 get_teximage_placement(struct gl_texture_image *ti)
305 {
306 if (ti->TexFormat == MESA_FORMAT_A8 ||
307 ti->TexFormat == MESA_FORMAT_L8 ||
308 ti->TexFormat == MESA_FORMAT_I8)
309 /* 1 cpp formats will have to be swizzled by the CPU,
310 * so leave them in system RAM for now. */
311 return NOUVEAU_BO_MAP;
312 else
313 return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
314 }
315
316 static void
317 nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
318 GLint internalFormat,
319 GLint width, GLint height, GLint depth, GLint border,
320 GLenum format, GLenum type, const GLvoid *pixels,
321 const struct gl_pixelstore_attrib *packing,
322 struct gl_texture_object *t,
323 struct gl_texture_image *ti)
324 {
325 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
326 int ret;
327
328 /* Allocate a new bo for the image. */
329 nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
330 ti->TexFormat, width, height);
331 ti->RowStride = s->pitch / s->cpp;
332
333 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
334 format, type, pixels, packing,
335 "glTexImage");
336 if (pixels) {
337 /* Store the pixel data. */
338 nouveau_teximage_map(ctx, ti);
339
340 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
341 ti->TexFormat, ti->Data,
342 0, 0, 0, s->pitch,
343 ti->ImageOffsets,
344 width, height, depth,
345 format, type, pixels, packing);
346 assert(ret);
347
348 nouveau_teximage_unmap(ctx, ti);
349 _mesa_unmap_teximage_pbo(ctx, packing);
350
351 if (!validate_teximage(ctx, t, level, 0, 0, 0,
352 width, height, depth))
353 /* It doesn't fit, mark it as dirty. */
354 texture_dirty(t);
355 }
356
357 if (level == t->BaseLevel) {
358 if (!teximage_fits(t, level, ti))
359 relayout_texture(ctx, t);
360 nouveau_texture_validate(ctx, t);
361 }
362
363 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
364 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
365 }
366
367 static void
368 nouveau_teximage_1d(GLcontext *ctx, GLenum target, GLint level,
369 GLint internalFormat,
370 GLint width, GLint border,
371 GLenum format, GLenum type, const GLvoid *pixels,
372 const struct gl_pixelstore_attrib *packing,
373 struct gl_texture_object *t,
374 struct gl_texture_image *ti)
375 {
376 nouveau_teximage(ctx, 1, target, level, internalFormat,
377 width, 1, 1, border, format, type, pixels,
378 packing, t, ti);
379 }
380
381 static void
382 nouveau_teximage_2d(GLcontext *ctx, GLenum target, GLint level,
383 GLint internalFormat,
384 GLint width, GLint height, GLint border,
385 GLenum format, GLenum type, const GLvoid *pixels,
386 const struct gl_pixelstore_attrib *packing,
387 struct gl_texture_object *t,
388 struct gl_texture_image *ti)
389 {
390 nouveau_teximage(ctx, 2, target, level, internalFormat,
391 width, height, 1, border, format, type, pixels,
392 packing, t, ti);
393 }
394
395 static void
396 nouveau_teximage_3d(GLcontext *ctx, GLenum target, GLint level,
397 GLint internalFormat,
398 GLint width, GLint height, GLint depth, GLint border,
399 GLenum format, GLenum type, const GLvoid *pixels,
400 const struct gl_pixelstore_attrib *packing,
401 struct gl_texture_object *t,
402 struct gl_texture_image *ti)
403 {
404 nouveau_teximage(ctx, 3, target, level, internalFormat,
405 width, height, depth, border, format, type, pixels,
406 packing, t, ti);
407 }
408
409 static void
410 nouveau_texsubimage_3d(GLcontext *ctx, GLenum target, GLint level,
411 GLint xoffset, GLint yoffset, GLint zoffset,
412 GLint width, GLint height, GLint depth,
413 GLenum format, GLenum type, const void *pixels,
414 const struct gl_pixelstore_attrib *packing,
415 struct gl_texture_object *t,
416 struct gl_texture_image *ti)
417 {
418 nouveau_teximage_map(ctx, ti);
419 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
420 width, height, depth, format, type, pixels,
421 packing, t, ti);
422 nouveau_teximage_unmap(ctx, ti);
423
424 if (!to_nouveau_texture(t)->dirty)
425 validate_teximage(ctx, t, level, xoffset, yoffset, zoffset,
426 width, height, depth);
427 }
428
429 static void
430 nouveau_texsubimage_2d(GLcontext *ctx, GLenum target, GLint level,
431 GLint xoffset, GLint yoffset,
432 GLint width, GLint height,
433 GLenum format, GLenum type, const void *pixels,
434 const struct gl_pixelstore_attrib *packing,
435 struct gl_texture_object *t,
436 struct gl_texture_image *ti)
437 {
438 nouveau_teximage_map(ctx, ti);
439 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset,
440 width, height, format, type, pixels,
441 packing, t, ti);
442 nouveau_teximage_unmap(ctx, ti);
443
444 if (!to_nouveau_texture(t)->dirty)
445 validate_teximage(ctx, t, level, xoffset, yoffset, 0,
446 width, height, 1);
447 }
448
449 static void
450 nouveau_texsubimage_1d(GLcontext *ctx, GLenum target, GLint level,
451 GLint xoffset, GLint width,
452 GLenum format, GLenum type, const void *pixels,
453 const struct gl_pixelstore_attrib *packing,
454 struct gl_texture_object *t,
455 struct gl_texture_image *ti)
456 {
457 nouveau_teximage_map(ctx, ti);
458 _mesa_store_texsubimage1d(ctx, target, level, xoffset,
459 width, format, type, pixels,
460 packing, t, ti);
461 nouveau_teximage_unmap(ctx, ti);
462
463 if (!to_nouveau_texture(t)->dirty)
464 validate_teximage(ctx, t, level, xoffset, 0, 0,
465 width, 1, 1);
466 }
467
468 static void
469 nouveau_get_teximage(GLcontext *ctx, GLenum target, GLint level,
470 GLenum format, GLenum type, GLvoid *pixels,
471 struct gl_texture_object *t,
472 struct gl_texture_image *ti)
473 {
474 nouveau_teximage_map(ctx, ti);
475 _mesa_get_teximage(ctx, target, level, format, type, pixels,
476 t, ti);
477 nouveau_teximage_unmap(ctx, ti);
478 }
479
480 static void
481 nouveau_bind_texture(GLcontext *ctx, GLenum target,
482 struct gl_texture_object *t)
483 {
484 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
485 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
486 }
487
488 static void
489 nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t)
490 {
491 int i;
492
493 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
494 if (t->Image[0][i])
495 nouveau_teximage_map(ctx, t->Image[0][i]);
496 }
497 }
498
499 static void
500 nouveau_texture_unmap(GLcontext *ctx, struct gl_texture_object *t)
501 {
502 int i;
503
504 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
505 if (t->Image[0][i])
506 nouveau_teximage_unmap(ctx, t->Image[0][i]);
507 }
508 }
509
510 void
511 nouveau_texture_functions_init(struct dd_function_table *functions)
512 {
513 functions->NewTextureObject = nouveau_texture_new;
514 functions->DeleteTexture = nouveau_texture_free;
515 functions->NewTextureImage = nouveau_teximage_new;
516 functions->FreeTexImageData = nouveau_teximage_free;
517 functions->ChooseTextureFormat = nouveau_choose_tex_format;
518 functions->TexImage1D = nouveau_teximage_1d;
519 functions->TexImage2D = nouveau_teximage_2d;
520 functions->TexImage3D = nouveau_teximage_3d;
521 functions->TexSubImage1D = nouveau_texsubimage_1d;
522 functions->TexSubImage2D = nouveau_texsubimage_2d;
523 functions->TexSubImage3D = nouveau_texsubimage_3d;
524 functions->GetTexImage = nouveau_get_teximage;
525 functions->BindTexture = nouveau_bind_texture;
526 functions->MapTexture = nouveau_texture_map;
527 functions->UnmapTexture = nouveau_texture_unmap;
528 }