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