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