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