Import a classic DRI driver for nv0x-nv2x.
[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 void
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)
182 {
183 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
184 unsigned bo_flags = NOUVEAU_BO_GART | NOUVEAU_BO_RDWR | NOUVEAU_BO_MAP;
185 int ret;
186
187 /* Allocate a new bo for the image. */
188 nouveau_surface_alloc(ctx, s, LINEAR, bo_flags, ti->TexFormat,
189 width, height);
190 ti->RowStride = s->pitch / s->cpp;
191
192 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
193 format, type, pixels, packing,
194 "glTexImage");
195 if (!pixels)
196 return;
197
198 /* Store the pixel data. */
199 nouveau_teximage_map(ctx, ti);
200
201 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
202 ti->TexFormat, ti->Data,
203 0, 0, 0, s->pitch,
204 ti->ImageOffsets,
205 width, height, depth,
206 format, type, pixels, packing);
207 assert(ret);
208
209 nouveau_teximage_unmap(ctx, ti);
210 _mesa_unmap_teximage_pbo(ctx, packing);
211
212 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
213 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
214 texture_dirty(t);
215 }
216
217 static void
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)
225 {
226 nouveau_teximage(ctx, 1, target, level, internalFormat,
227 width, 1, 1, border, format, type, pixels,
228 packing, t, ti);
229 }
230
231 static void
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)
239 {
240 nouveau_teximage(ctx, 2, target, level, internalFormat,
241 width, height, 1, border, format, type, pixels,
242 packing, t, ti);
243 }
244
245 static void
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)
253 {
254 nouveau_teximage(ctx, 3, target, level, internalFormat,
255 width, height, depth, border, format, type, pixels,
256 packing, t, ti);
257 }
258
259 static void
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)
267 {
268 nouveau_teximage_map(ctx, ti);
269 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
270 width, height, depth, format, type, pixels,
271 packing, t, ti);
272 nouveau_teximage_unmap(ctx, ti);
273
274 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
275 texture_dirty(t);
276 }
277
278 static void
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)
286 {
287 nouveau_teximage_map(ctx, ti);
288 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset,
289 width, height, format, type, pixels,
290 packing, t, ti);
291 nouveau_teximage_unmap(ctx, ti);
292
293 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
294 texture_dirty(t);
295 }
296
297 static void
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)
304 {
305 nouveau_teximage_map(ctx, ti);
306 _mesa_store_texsubimage1d(ctx, target, level, xoffset,
307 width, format, type, pixels,
308 packing, t, ti);
309 nouveau_teximage_unmap(ctx, ti);
310
311 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
312 texture_dirty(t);
313 }
314
315 static void
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)
320 {
321 nouveau_teximage_map(ctx, ti);
322 _mesa_get_teximage(ctx, target, level, format, type, pixels,
323 t, ti);
324 nouveau_teximage_unmap(ctx, ti);
325 }
326
327 static void
328 nouveau_bind_texture(GLcontext *ctx, GLenum target,
329 struct gl_texture_object *t)
330 {
331 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
332 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
333 }
334
335 static void
336 nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t)
337 {
338 int i;
339
340 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
341 if (t->Image[0][i])
342 nouveau_teximage_map(ctx, t->Image[0][i]);
343 }
344 }
345
346 static void
347 nouveau_texture_unmap(GLcontext *ctx, struct gl_texture_object *t)
348 {
349 int i;
350
351 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
352 if (t->Image[0][i])
353 nouveau_teximage_unmap(ctx, t->Image[0][i]);
354 }
355 }
356
357 static void
358 relayout_miptree(GLcontext *ctx, struct gl_texture_object *t)
359 {
360 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
361 unsigned last_level, offset = 0;
362 unsigned size;
363 int i, ret;
364
365 if (t->MinFilter == GL_NEAREST ||
366 t->MinFilter == GL_LINEAR)
367 last_level = t->BaseLevel;
368 else
369 last_level = t->_MaxLevel;
370
371 /* Deallocate the old storage. */
372 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
373 nouveau_bo_ref(NULL, &ss[i].bo);
374
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;
379
380 size = s->width * s->height * s->cpp;
381
382 /* Images larger than 16B have to be aligned. */
383 if (size > 16)
384 offset = align(offset, 64);
385
386 ss[i] = (struct nouveau_surface) {
387 .offset = offset,
388 .layout = SWIZZLED,
389 .format = s->format,
390 .width = s->width,
391 .height = s->height,
392 .cpp = s->cpp,
393 .pitch = s->width * s->cpp,
394 };
395
396 offset += size;
397 }
398
399 /* Get new storage. */
400 size = align(offset, 64);
401
402 ret = nouveau_bo_new(context_dev(ctx),
403 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
404 0, size, &ss[last_level].bo);
405 assert(!ret);
406
407 for (i = t->BaseLevel; i < last_level; i++)
408 nouveau_bo_ref(ss[last_level].bo, &ss[i].bo);
409 }
410
411 void
412 nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t)
413 {
414 struct nouveau_texture *nt = to_nouveau_texture(t);
415 int i;
416
417 if (!nt->dirty)
418 return;
419
420 nt->dirty = GL_FALSE;
421
422 relayout_miptree(ctx, t);
423
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;
428
429 if (!nt->surfaces[i].bo)
430 break;
431
432 context_drv(ctx)->surface_copy(ctx, &nt->surfaces[i], s,
433 0, 0, 0, 0,
434 s->width, s->height);
435 }
436 }
437
438 void
439 nouveau_texture_functions_init(struct dd_function_table *functions)
440 {
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;
456 }