blob: 6b361b0a4b6b983acf962012365a925511c94734 [file] [log] [blame]
Brian24df8f82007-08-06 15:48:42 -06001/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "main/imports.h"
29#include "main/convolve.h"
30#include "main/enums.h"
31#include "main/image.h"
32#include "main/macros.h"
33#include "main/texcompress.h"
34#include "main/texformat.h"
35#include "main/teximage.h"
36#include "main/texobj.h"
37#include "main/texstore.h"
38
39#include "state_tracker/st_context.h"
40#include "state_tracker/st_cb_texture.h"
41#include "state_tracker/st_mipmap_tree.h"
42
43#include "pipe/p_context.h"
Brianb2458402007-08-07 18:18:54 -060044#include "pipe/p_defines.h"
Brian24df8f82007-08-06 15:48:42 -060045
46
47#define DBG if (0) printf
48
49
50struct st_texture_object
51{
52 struct gl_texture_object base; /* The "parent" object */
53
54 /* The mipmap tree must include at least these levels once
55 * validated:
56 */
57 GLuint firstLevel;
58 GLuint lastLevel;
59
60 /* Offset for firstLevel image:
61 */
62 GLuint textureOffset;
63
64 /* On validation any active images held in main memory or in other
65 * regions will be copied to this region and the old storage freed.
66 */
67 struct pipe_mipmap_tree *mt;
68
69 GLboolean imageOverride;
70 GLint depthOverride;
71 GLuint pitchOverride;
72};
73
74
75
76struct st_texture_image
77{
78 struct gl_texture_image base;
79
80 /* These aren't stored in gl_texture_image
81 */
82 GLuint level;
83 GLuint face;
84
85 /* If stImage->mt != NULL, image data is stored here.
86 * Else if stImage->base.Data != NULL, image is stored there.
87 * Else there is no image data.
88 */
89 struct pipe_mipmap_tree *mt;
90};
91
92
93
94
95static INLINE struct st_texture_object *
96st_texture_object(struct gl_texture_object *obj)
97{
98 return (struct st_texture_object *) obj;
99}
100
101static INLINE struct st_texture_image *
102st_texture_image(struct gl_texture_image *img)
103{
104 return (struct st_texture_image *) img;
105}
106
107
Briand78dab12007-08-07 15:12:22 -0600108struct pipe_mipmap_tree *
109st_get_texobj_mipmap_tree(struct gl_texture_object *texObj)
110{
111 struct st_texture_object *stObj = st_texture_object(texObj);
112 return stObj->mt;
113}
114
115
Brianb2458402007-08-07 18:18:54 -0600116static GLuint
117mesa_format_to_pipe_format(GLuint mesaFormat)
118{
119 switch (mesaFormat) {
120 /* fix this */
121 case MESA_FORMAT_ARGB8888_REV:
122 case MESA_FORMAT_ARGB8888:
123 return PIPE_FORMAT_U_A8_R8_G8_B8;
124 default:
125 assert(0);
126 return 0;
127 }
128}
129
130
Brian24df8f82007-08-06 15:48:42 -0600131static int
Brian14b98342007-08-07 16:42:08 -0600132compressed_num_bytes(GLuint mesaFormat)
Brian24df8f82007-08-06 15:48:42 -0600133{
134 int bytes = 0;
135 switch(mesaFormat) {
136
137 case MESA_FORMAT_RGB_FXT1:
138 case MESA_FORMAT_RGBA_FXT1:
139 case MESA_FORMAT_RGB_DXT1:
140 case MESA_FORMAT_RGBA_DXT1:
141 bytes = 2;
142 break;
143
144 case MESA_FORMAT_RGBA_DXT3:
145 case MESA_FORMAT_RGBA_DXT5:
146 bytes = 4;
147 default:
148 break;
149 }
150
151 return bytes;
152}
153
154
155/* It works out that this function is fine for all the supported
156 * hardware. However, there is still a need to map the formats onto
157 * hardware descriptors.
158 */
159/* Note that the i915 can actually support many more formats than
160 * these if we take the step of simply swizzling the colors
161 * immediately after sampling...
162 */
163static const struct gl_texture_format *
164st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
165 GLenum format, GLenum type)
166{
167#if 0
168 struct intel_context *intel = intel_context(ctx);
169 const GLboolean do32bpt = (intel->intelScreen->front.cpp == 4);
170#else
171 const GLboolean do32bpt = 1;
172#endif
173
174 switch (internalFormat) {
175 case 4:
176 case GL_RGBA:
177 case GL_COMPRESSED_RGBA:
178 if (format == GL_BGRA) {
179 if (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) {
180 return &_mesa_texformat_argb8888;
181 }
182 else if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
183 return &_mesa_texformat_argb4444;
184 }
185 else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
186 return &_mesa_texformat_argb1555;
187 }
188 }
189 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
190
191 case 3:
192 case GL_RGB:
193 case GL_COMPRESSED_RGB:
194 if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
195 return &_mesa_texformat_rgb565;
196 }
197 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
198
199 case GL_RGBA8:
200 case GL_RGB10_A2:
201 case GL_RGBA12:
202 case GL_RGBA16:
203 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
204
205 case GL_RGBA4:
206 case GL_RGBA2:
207 return &_mesa_texformat_argb4444;
208
209 case GL_RGB5_A1:
210 return &_mesa_texformat_argb1555;
211
212 case GL_RGB8:
213 case GL_RGB10:
214 case GL_RGB12:
215 case GL_RGB16:
216 return &_mesa_texformat_argb8888;
217
218 case GL_RGB5:
219 case GL_RGB4:
220 case GL_R3_G3_B2:
221 return &_mesa_texformat_rgb565;
222
223 case GL_ALPHA:
224 case GL_ALPHA4:
225 case GL_ALPHA8:
226 case GL_ALPHA12:
227 case GL_ALPHA16:
228 case GL_COMPRESSED_ALPHA:
229 return &_mesa_texformat_a8;
230
231 case 1:
232 case GL_LUMINANCE:
233 case GL_LUMINANCE4:
234 case GL_LUMINANCE8:
235 case GL_LUMINANCE12:
236 case GL_LUMINANCE16:
237 case GL_COMPRESSED_LUMINANCE:
238 return &_mesa_texformat_l8;
239
240 case 2:
241 case GL_LUMINANCE_ALPHA:
242 case GL_LUMINANCE4_ALPHA4:
243 case GL_LUMINANCE6_ALPHA2:
244 case GL_LUMINANCE8_ALPHA8:
245 case GL_LUMINANCE12_ALPHA4:
246 case GL_LUMINANCE12_ALPHA12:
247 case GL_LUMINANCE16_ALPHA16:
248 case GL_COMPRESSED_LUMINANCE_ALPHA:
249 return &_mesa_texformat_al88;
250
251 case GL_INTENSITY:
252 case GL_INTENSITY4:
253 case GL_INTENSITY8:
254 case GL_INTENSITY12:
255 case GL_INTENSITY16:
256 case GL_COMPRESSED_INTENSITY:
257 return &_mesa_texformat_i8;
258
259 case GL_YCBCR_MESA:
260 if (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE)
261 return &_mesa_texformat_ycbcr;
262 else
263 return &_mesa_texformat_ycbcr_rev;
264
265 case GL_COMPRESSED_RGB_FXT1_3DFX:
266 return &_mesa_texformat_rgb_fxt1;
267 case GL_COMPRESSED_RGBA_FXT1_3DFX:
268 return &_mesa_texformat_rgba_fxt1;
269
270 case GL_RGB_S3TC:
271 case GL_RGB4_S3TC:
272 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
273 return &_mesa_texformat_rgb_dxt1;
274
275 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
276 return &_mesa_texformat_rgba_dxt1;
277
278 case GL_RGBA_S3TC:
279 case GL_RGBA4_S3TC:
280 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
281 return &_mesa_texformat_rgba_dxt3;
282
283 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
284 return &_mesa_texformat_rgba_dxt5;
285
286 case GL_DEPTH_COMPONENT:
287 case GL_DEPTH_COMPONENT16:
288 case GL_DEPTH_COMPONENT24:
289 case GL_DEPTH_COMPONENT32:
290 return &_mesa_texformat_z16;
291
292 case GL_DEPTH_STENCIL_EXT:
293 case GL_DEPTH24_STENCIL8_EXT:
294 return &_mesa_texformat_z24_s8;
295
296 default:
297 fprintf(stderr, "unexpected texture format %s in %s\n",
298 _mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__);
299 return NULL;
300 }
301
302 return NULL; /* never get here */
303}
304
305
306static GLboolean
307st_IsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj)
308{
309#if 0
310 struct intel_context *intel = intel_context(ctx);
311 struct st_texture_object *stObj = st_texture_object(texObj);
312
313 return
314 stObj->mt &&
315 stObj->mt->region &&
316 intel_is_region_resident(intel, stObj->mt->region);
317#endif
318 return 1;
319}
320
321
322
323static struct gl_texture_image *
324st_NewTextureImage(GLcontext * ctx)
325{
326 DBG("%s\n", __FUNCTION__);
327 (void) ctx;
328 return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image);
329}
330
331
332static struct gl_texture_object *
333st_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
334{
335 struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object);
336
337 DBG("%s\n", __FUNCTION__);
338 _mesa_initialize_texture_object(&obj->base, name, target);
339
340 return &obj->base;
341}
342
343static void
344st_DeleteTextureObject(GLcontext *ctx,
345 struct gl_texture_object *texObj)
346{
347 struct pipe_context *pipe = ctx->st->pipe;
348 struct st_texture_object *stObj = st_texture_object(texObj);
349
350 if (stObj->mt)
351 st_miptree_release(pipe, &stObj->mt);
352
353 _mesa_delete_texture_object(ctx, texObj);
354}
355
356
357static void
358st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
359{
360 struct pipe_context *pipe = ctx->st->pipe;
361 struct st_texture_image *stImage = st_texture_image(texImage);
362
363 DBG("%s\n", __FUNCTION__);
364
365 if (stImage->mt) {
366 st_miptree_release(pipe, &stImage->mt);
367 }
368
369 if (texImage->Data) {
370 free(texImage->Data);
371 texImage->Data = NULL;
372 }
373}
374
375
376
377
378/* ================================================================
379 * From linux kernel i386 header files, copes with odd sizes better
380 * than COPY_DWORDS would:
381 * XXX Put this in src/mesa/main/imports.h ???
382 */
383#if defined(i386) || defined(__i386__)
384static INLINE void *
385__memcpy(void *to, const void *from, size_t n)
386{
387 int d0, d1, d2;
388 __asm__ __volatile__("rep ; movsl\n\t"
389 "testb $2,%b4\n\t"
390 "je 1f\n\t"
391 "movsw\n"
392 "1:\ttestb $1,%b4\n\t"
393 "je 2f\n\t"
394 "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
395 :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
396 :"memory");
397 return (to);
398}
399#else
400#define __memcpy(a,b,c) memcpy(a,b,c)
401#endif
402
403
404/* The system memcpy (at least on ubuntu 5.10) has problems copying
405 * to agp (writecombined) memory from a source which isn't 64-byte
406 * aligned - there is a 4x performance falloff.
407 *
408 * The x86 __memcpy is immune to this but is slightly slower
409 * (10%-ish) than the system memcpy.
410 *
411 * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
412 * isn't much faster than x86_memcpy for agp copies.
413 *
414 * TODO: switch dynamically.
415 */
416static void *
417do_memcpy(void *dest, const void *src, size_t n)
418{
419 if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
420 return __memcpy(dest, src, n);
421 }
422 else
423 return memcpy(dest, src, n);
424}
425
426
427/* Functions to store texture images. Where possible, mipmap_tree's
428 * will be created or further instantiated with image data, otherwise
429 * images will be stored in malloc'd memory. A validation step is
430 * required to pull those images into a mipmap tree, or otherwise
431 * decide a fallback is required.
432 */
433
434
435static int
436logbase2(int n)
437{
438 GLint i = 1;
439 GLint log2 = 0;
440
441 while (n > i) {
442 i *= 2;
443 log2++;
444 }
445
446 return log2;
447}
448
449
450/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
451 * 1).
452 *
453 * Otherwise, if max_level >= level >= min_level, create tree with
454 * space for textures from min_level down to max_level.
455 *
456 * Otherwise, create tree with space for textures from (level
457 * 0)..(1x1). Consider pruning this tree at a validation if the
458 * saving is worth it.
459 */
460static void
461guess_and_alloc_mipmap_tree(struct pipe_context *pipe,
Brian14b98342007-08-07 16:42:08 -0600462 struct st_texture_object *stObj,
463 struct st_texture_image *stImage)
Brian24df8f82007-08-06 15:48:42 -0600464{
465 GLuint firstLevel;
466 GLuint lastLevel;
Brian14b98342007-08-07 16:42:08 -0600467 GLuint width = stImage->base.Width;
468 GLuint height = stImage->base.Height;
469 GLuint depth = stImage->base.Depth;
Brian24df8f82007-08-06 15:48:42 -0600470 GLuint l2width, l2height, l2depth;
471 GLuint i, comp_byte = 0;
472
473 DBG("%s\n", __FUNCTION__);
474
Brian14b98342007-08-07 16:42:08 -0600475 if (stImage->base.Border)
Brian24df8f82007-08-06 15:48:42 -0600476 return;
477
Brian14b98342007-08-07 16:42:08 -0600478 if (stImage->level > stObj->base.BaseLevel &&
479 (stImage->base.Width == 1 ||
480 (stObj->base.Target != GL_TEXTURE_1D &&
481 stImage->base.Height == 1) ||
482 (stObj->base.Target == GL_TEXTURE_3D &&
483 stImage->base.Depth == 1)))
Brian24df8f82007-08-06 15:48:42 -0600484 return;
485
486 /* If this image disrespects BaseLevel, allocate from level zero.
487 * Usually BaseLevel == 0, so it's unlikely to happen.
488 */
Brian14b98342007-08-07 16:42:08 -0600489 if (stImage->level < stObj->base.BaseLevel)
Brian24df8f82007-08-06 15:48:42 -0600490 firstLevel = 0;
491 else
Brian14b98342007-08-07 16:42:08 -0600492 firstLevel = stObj->base.BaseLevel;
Brian24df8f82007-08-06 15:48:42 -0600493
494
495 /* Figure out image dimensions at start level.
496 */
Brian14b98342007-08-07 16:42:08 -0600497 for (i = stImage->level; i > firstLevel; i--) {
Brian24df8f82007-08-06 15:48:42 -0600498 width <<= 1;
499 if (height != 1)
500 height <<= 1;
501 if (depth != 1)
502 depth <<= 1;
503 }
504
505 /* Guess a reasonable value for lastLevel. This is probably going
506 * to be wrong fairly often and might mean that we have to look at
507 * resizable buffers, or require that buffers implement lazy
508 * pagetable arrangements.
509 */
Brian14b98342007-08-07 16:42:08 -0600510 if ((stObj->base.MinFilter == GL_NEAREST ||
511 stObj->base.MinFilter == GL_LINEAR) &&
512 stImage->level == firstLevel) {
Brian24df8f82007-08-06 15:48:42 -0600513 lastLevel = firstLevel;
514 }
515 else {
516 l2width = logbase2(width);
517 l2height = logbase2(height);
518 l2depth = logbase2(depth);
519 lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
520 }
521
Brian14b98342007-08-07 16:42:08 -0600522 assert(!stObj->mt);
523 if (stImage->base.IsCompressed)
524 comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
525 stObj->mt = st_miptree_create(pipe,
526 stObj->base.Target,
527 stImage->base.InternalFormat,
Brian24df8f82007-08-06 15:48:42 -0600528 firstLevel,
529 lastLevel,
530 width,
531 height,
532 depth,
Brian14b98342007-08-07 16:42:08 -0600533 stImage->base.TexFormat->TexelBytes,
Brian24df8f82007-08-06 15:48:42 -0600534 comp_byte);
535
Brianb2458402007-08-07 18:18:54 -0600536 stObj->mt->format
537 = mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
538
Brian24df8f82007-08-06 15:48:42 -0600539 DBG("%s - success\n", __FUNCTION__);
540}
541
542
543
544
545static GLuint
546target_to_face(GLenum target)
547{
548 switch (target) {
549 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
550 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
551 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
552 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
553 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
554 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
555 return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
556 default:
557 return 0;
558 }
559}
560
561
562
563/* There are actually quite a few combinations this will work for,
564 * more than what I've listed here.
565 */
566static GLboolean
567check_pbo_format(GLint internalFormat,
568 GLenum format, GLenum type,
569 const struct gl_texture_format *mesa_format)
570{
571 switch (internalFormat) {
572 case 4:
573 case GL_RGBA:
574 return (format == GL_BGRA &&
575 (type == GL_UNSIGNED_BYTE ||
576 type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
577 mesa_format == &_mesa_texformat_argb8888);
578 case 3:
579 case GL_RGB:
580 return (format == GL_RGB &&
581 type == GL_UNSIGNED_SHORT_5_6_5 &&
582 mesa_format == &_mesa_texformat_rgb565);
583 case GL_YCBCR_MESA:
584 return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE);
585 default:
586 return GL_FALSE;
587 }
588}
589
590
591/* XXX: Do this for TexSubImage also:
592 */
593static GLboolean
594try_pbo_upload(GLcontext *ctx,
Brian14b98342007-08-07 16:42:08 -0600595 struct st_texture_image *stImage,
Brian24df8f82007-08-06 15:48:42 -0600596 const struct gl_pixelstore_attrib *unpack,
597 GLint internalFormat,
598 GLint width, GLint height,
599 GLenum format, GLenum type, const void *pixels)
600{
601 return GL_FALSE; /* XXX fix flushing/locking/blitting below */
602#if 000
603 struct intel_context *intel = intel_context(ctx);
604 struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
605 GLuint src_offset, src_stride;
606 GLuint dst_offset, dst_stride;
607
608 if (!pbo ||
609 ctx._ImageTransferState ||
610 unpack->SkipPixels || unpack->SkipRows) {
611 _mesa_printf("%s: failure 1\n", __FUNCTION__);
612 return GL_FALSE;
613 }
614
615 src_offset = (GLuint) pixels;
616
617 if (unpack->RowLength > 0)
618 src_stride = unpack->RowLength;
619 else
620 src_stride = width;
621
Brian14b98342007-08-07 16:42:08 -0600622 dst_offset = st_miptree_image_offset(stImage->mt,
623 stImage->face,
624 stImage->level);
Brian24df8f82007-08-06 15:48:42 -0600625
Brian14b98342007-08-07 16:42:08 -0600626 dst_stride = stImage->mt->pitch;
Brian24df8f82007-08-06 15:48:42 -0600627
628 intelFlush(&intel->ctx);
629 LOCK_HARDWARE(intel);
630 {
631 struct _DriBufferObject *src_buffer =
632 intel_bufferobj_buffer(intel, pbo, INTEL_READ);
633
634 /* Temporary hack: cast to _DriBufferObject:
635 */
636 struct _DriBufferObject *dst_buffer =
Brian14b98342007-08-07 16:42:08 -0600637 (struct _DriBufferObject *)stImage->mt->region->buffer;
Brian24df8f82007-08-06 15:48:42 -0600638
639
640 intelEmitCopyBlit(intel,
Brian14b98342007-08-07 16:42:08 -0600641 stImage->mt->cpp,
Brian24df8f82007-08-06 15:48:42 -0600642 src_stride, src_buffer, src_offset,
643 dst_stride, dst_buffer, dst_offset,
644 0, 0, 0, 0, width, height,
645 GL_COPY);
646
647 intel_batchbuffer_flush(intel->batch);
648 }
649 UNLOCK_HARDWARE(intel);
650
651 return GL_TRUE;
652#endif
653}
654
655
656
657static GLboolean
658try_pbo_zcopy(GLcontext *ctx,
Brian14b98342007-08-07 16:42:08 -0600659 struct st_texture_image *stImage,
Brian24df8f82007-08-06 15:48:42 -0600660 const struct gl_pixelstore_attrib *unpack,
661 GLint internalFormat,
662 GLint width, GLint height,
663 GLenum format, GLenum type, const void *pixels)
664{
665 return GL_FALSE;
666}
667
668
669
670
671
672
673static void
674st_TexImage(GLcontext * ctx,
675 GLint dims,
676 GLenum target, GLint level,
677 GLint internalFormat,
678 GLint width, GLint height, GLint depth,
679 GLint border,
680 GLenum format, GLenum type, const void *pixels,
681 const struct gl_pixelstore_attrib *unpack,
682 struct gl_texture_object *texObj,
683 struct gl_texture_image *texImage, GLsizei imageSize, int compressed)
684{
685 struct pipe_context *pipe = ctx->st->pipe;
Brian14b98342007-08-07 16:42:08 -0600686 struct st_texture_object *stObj = st_texture_object(texObj);
687 struct st_texture_image *stImage = st_texture_image(texImage);
Brian24df8f82007-08-06 15:48:42 -0600688 GLint postConvWidth = width;
689 GLint postConvHeight = height;
690 GLint texelBytes, sizeInBytes;
691 GLuint dstRowStride;
692
693
694 DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
695 _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
696
697#if 0
698 intelFlush(ctx);
699#endif
700
Brian14b98342007-08-07 16:42:08 -0600701 stImage->face = target_to_face(target);
702 stImage->level = level;
Brian24df8f82007-08-06 15:48:42 -0600703
704 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
705 _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
706 &postConvHeight);
707 }
708
709 /* choose the texture format */
710 texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
711 format, type);
712
713 _mesa_set_fetch_functions(texImage, dims);
714
715 if (texImage->TexFormat->TexelBytes == 0) {
716 /* must be a compressed format */
717 texelBytes = 0;
718 texImage->IsCompressed = GL_TRUE;
719 texImage->CompressedSize =
720 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
721 texImage->Height, texImage->Depth,
722 texImage->TexFormat->MesaFormat);
723 } else {
724 texelBytes = texImage->TexFormat->TexelBytes;
725
726 /* Minimum pitch of 32 bytes */
727 if (postConvWidth * texelBytes < 32) {
728 postConvWidth = 32 / texelBytes;
729 texImage->RowStride = postConvWidth;
730 }
731
732 assert(texImage->RowStride == postConvWidth);
733 }
734
735 /* Release the reference to a potentially orphaned buffer.
736 * Release any old malloced memory.
737 */
Brian14b98342007-08-07 16:42:08 -0600738 if (stImage->mt) {
739 st_miptree_release(pipe, &stImage->mt);
Brian24df8f82007-08-06 15:48:42 -0600740 assert(!texImage->Data);
741 }
742 else if (texImage->Data) {
743 _mesa_align_free(texImage->Data);
744 }
745
746 /* If this is the only texture image in the tree, could call
747 * bmBufferData with NULL data to free the old block and avoid
748 * waiting on any outstanding fences.
749 */
Brian14b98342007-08-07 16:42:08 -0600750 if (stObj->mt &&
751 stObj->mt->first_level == level &&
752 stObj->mt->last_level == level &&
753 stObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
754 !st_miptree_match_image(stObj->mt, &stImage->base,
755 stImage->face, stImage->level)) {
Brian24df8f82007-08-06 15:48:42 -0600756
757 DBG("release it\n");
Brian14b98342007-08-07 16:42:08 -0600758 st_miptree_release(pipe, &stObj->mt);
759 assert(!stObj->mt);
Brian24df8f82007-08-06 15:48:42 -0600760 }
761
Brian14b98342007-08-07 16:42:08 -0600762 if (!stObj->mt) {
763 guess_and_alloc_mipmap_tree(pipe, stObj, stImage);
764 if (!stObj->mt) {
Brian24df8f82007-08-06 15:48:42 -0600765 DBG("guess_and_alloc_mipmap_tree: failed\n");
766 }
767 }
768
Brian14b98342007-08-07 16:42:08 -0600769 assert(!stImage->mt);
Brian24df8f82007-08-06 15:48:42 -0600770
Brian14b98342007-08-07 16:42:08 -0600771 if (stObj->mt &&
772 st_miptree_match_image(stObj->mt, &stImage->base,
773 stImage->face, stImage->level)) {
Brian24df8f82007-08-06 15:48:42 -0600774
Brian14b98342007-08-07 16:42:08 -0600775 st_miptree_reference(&stImage->mt, stObj->mt);
776 assert(stImage->mt);
Brian24df8f82007-08-06 15:48:42 -0600777 }
778
Brian14b98342007-08-07 16:42:08 -0600779 if (!stImage->mt)
Brian24df8f82007-08-06 15:48:42 -0600780 DBG("XXX: Image did not fit into tree - storing in local memory!\n");
781
782#if 0 /* XXX FIX when st_buffer_objects are in place */
783 /* PBO fastpaths:
784 */
785 if (dims <= 2 &&
Brian14b98342007-08-07 16:42:08 -0600786 stImage->mt &&
Brian24df8f82007-08-06 15:48:42 -0600787 intel_buffer_object(unpack->BufferObj) &&
788 check_pbo_format(internalFormat, format,
Brian14b98342007-08-07 16:42:08 -0600789 type, stImage->base.TexFormat)) {
Brian24df8f82007-08-06 15:48:42 -0600790
791 DBG("trying pbo upload\n");
792
793 /* Attempt to texture directly from PBO data (zero copy upload).
794 *
795 * Currently disable as it can lead to worse as well as better
796 * performance (in particular when pipe_region_cow() is
797 * required).
798 */
Brian14b98342007-08-07 16:42:08 -0600799 if (stObj->mt == stImage->mt &&
800 stObj->mt->first_level == level &&
801 stObj->mt->last_level == level) {
Brian24df8f82007-08-06 15:48:42 -0600802
Brian14b98342007-08-07 16:42:08 -0600803 if (try_pbo_zcopy(intel, stImage, unpack,
Brian24df8f82007-08-06 15:48:42 -0600804 internalFormat,
805 width, height, format, type, pixels)) {
806
807 DBG("pbo zcopy upload succeeded\n");
808 return;
809 }
810 }
811
812
813 /* Otherwise, attempt to use the blitter for PBO image uploads.
814 */
Brian14b98342007-08-07 16:42:08 -0600815 if (try_pbo_upload(intel, stImage, unpack,
Brian24df8f82007-08-06 15:48:42 -0600816 internalFormat,
817 width, height, format, type, pixels)) {
818 DBG("pbo upload succeeded\n");
819 return;
820 }
821
822 DBG("pbo upload failed\n");
823 }
824#else
825 (void) try_pbo_upload;
826 (void) check_pbo_format;
827 (void) try_pbo_zcopy;
828#endif
829
830
831 /* intelCopyTexImage calls this function with pixels == NULL, with
832 * the expectation that the mipmap tree will be set up but nothing
833 * more will be done. This is where those calls return:
834 */
835 if (compressed) {
836 pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
837 unpack,
838 "glCompressedTexImage");
839 } else {
840 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
841 format, type,
842 pixels, unpack, "glTexImage");
843 }
844 if (!pixels)
845 return;
846
847
Brian14b98342007-08-07 16:42:08 -0600848 if (stImage->mt)
849 pipe->region_idle(pipe, stImage->mt->region);
Brian24df8f82007-08-06 15:48:42 -0600850
851#if 0
852 LOCK_HARDWARE(intel);
853#endif
854
Brian14b98342007-08-07 16:42:08 -0600855 if (stImage->mt) {
Brian24df8f82007-08-06 15:48:42 -0600856 texImage->Data = st_miptree_image_map(pipe,
Brian14b98342007-08-07 16:42:08 -0600857 stImage->mt,
858 stImage->face,
859 stImage->level,
Brian24df8f82007-08-06 15:48:42 -0600860 &dstRowStride,
Brian14b98342007-08-07 16:42:08 -0600861 stImage->base.ImageOffsets);
Brian24df8f82007-08-06 15:48:42 -0600862 }
863 else {
864 /* Allocate regular memory and store the image there temporarily. */
865 if (texImage->IsCompressed) {
866 sizeInBytes = texImage->CompressedSize;
867 dstRowStride =
868 _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
869 assert(dims != 3);
870 }
871 else {
872 dstRowStride = postConvWidth * texelBytes;
873 sizeInBytes = depth * dstRowStride * postConvHeight;
874 }
875
876 texImage->Data = malloc(sizeInBytes);
877 }
878
879 DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
880 width, height, depth, width * texelBytes, dstRowStride);
881
882 /* Copy data. Would like to know when it's ok for us to eg. use
883 * the blitter to copy. Or, use the hardware to do the format
884 * conversion and copy:
885 */
886 if (compressed) {
887 memcpy(texImage->Data, pixels, imageSize);
888 }
889 else if (!texImage->TexFormat->StoreImage(ctx, dims,
890 texImage->_BaseFormat,
891 texImage->TexFormat,
892 texImage->Data,
893 0, 0, 0, /* dstX/Y/Zoffset */
894 dstRowStride,
895 texImage->ImageOffsets,
896 width, height, depth,
897 format, type, pixels, unpack)) {
898 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
899 }
900
901 _mesa_unmap_teximage_pbo(ctx, unpack);
902
Brian14b98342007-08-07 16:42:08 -0600903 if (stImage->mt) {
904 st_miptree_image_unmap(pipe, stImage->mt);
Brian24df8f82007-08-06 15:48:42 -0600905 texImage->Data = NULL;
906 }
907
908#if 0
909 UNLOCK_HARDWARE(intel);
910#endif
911
912#if 0
913 /* GL_SGIS_generate_mipmap -- this can be accelerated now.
914 */
915 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
916 intel_generate_mipmap(ctx, target,
917 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
918 texObj);
919 }
920#endif
921}
922
923
924static void
925st_TexImage3D(GLcontext * ctx,
926 GLenum target, GLint level,
927 GLint internalFormat,
928 GLint width, GLint height, GLint depth,
929 GLint border,
930 GLenum format, GLenum type, const void *pixels,
931 const struct gl_pixelstore_attrib *unpack,
932 struct gl_texture_object *texObj,
933 struct gl_texture_image *texImage)
934{
935 st_TexImage(ctx, 3, target, level,
936 internalFormat, width, height, depth, border,
937 format, type, pixels, unpack, texObj, texImage, 0, 0);
938}
939
940
941static void
942st_TexImage2D(GLcontext * ctx,
943 GLenum target, GLint level,
944 GLint internalFormat,
945 GLint width, GLint height, GLint border,
946 GLenum format, GLenum type, const void *pixels,
947 const struct gl_pixelstore_attrib *unpack,
948 struct gl_texture_object *texObj,
949 struct gl_texture_image *texImage)
950{
951 st_TexImage(ctx, 2, target, level,
952 internalFormat, width, height, 1, border,
953 format, type, pixels, unpack, texObj, texImage, 0, 0);
954}
955
956
957static void
958st_TexImage1D(GLcontext * ctx,
959 GLenum target, GLint level,
960 GLint internalFormat,
961 GLint width, GLint border,
962 GLenum format, GLenum type, const void *pixels,
963 const struct gl_pixelstore_attrib *unpack,
964 struct gl_texture_object *texObj,
965 struct gl_texture_image *texImage)
966{
967 st_TexImage(ctx, 1, target, level,
968 internalFormat, width, 1, 1, border,
969 format, type, pixels, unpack, texObj, texImage, 0, 0);
970}
971
972
973static void
974st_CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
975 GLint internalFormat,
976 GLint width, GLint height, GLint border,
977 GLsizei imageSize, const GLvoid *data,
978 struct gl_texture_object *texObj,
979 struct gl_texture_image *texImage )
980{
981 st_TexImage(ctx, 2, target, level,
982 internalFormat, width, height, 1, border,
983 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
984}
985
986
987/**
988 * Need to map texture image into memory before copying image data,
989 * then unmap it.
990 */
991static void
992st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
993 GLenum format, GLenum type, GLvoid * pixels,
994 struct gl_texture_object *texObj,
995 struct gl_texture_image *texImage, int compressed)
996{
997 /*
998 struct intel_context *intel = intel_context(ctx);
999 */
1000 struct pipe_context *pipe = ctx->st->pipe;
1001 struct st_texture_image *stImage = st_texture_image(texImage);
1002
1003 /* Map */
1004 if (stImage->mt) {
1005 /* Image is stored in hardware format in a buffer managed by the
1006 * kernel. Need to explicitly map and unmap it.
1007 */
1008 stImage->base.Data =
1009 st_miptree_image_map(pipe,
1010 stImage->mt,
1011 stImage->face,
1012 stImage->level,
1013 &stImage->base.RowStride,
1014 stImage->base.ImageOffsets);
1015 stImage->base.RowStride /= stImage->mt->cpp;
1016 }
1017 else {
1018 /* Otherwise, the image should actually be stored in
1019 * stImage->base.Data. This is pretty confusing for
1020 * everybody, I'd much prefer to separate the two functions of
1021 * texImage->Data - storage for texture images in main memory
1022 * and access (ie mappings) of images. In other words, we'd
1023 * create a new texImage->Map field and leave Data simply for
1024 * storage.
1025 */
1026 assert(stImage->base.Data);
1027 }
1028
1029
1030 if (compressed) {
1031 _mesa_get_compressed_teximage(ctx, target, level, pixels,
1032 texObj, texImage);
1033 } else {
1034 _mesa_get_teximage(ctx, target, level, format, type, pixels,
1035 texObj, texImage);
1036 }
1037
1038
1039 /* Unmap */
1040 if (stImage->mt) {
1041 st_miptree_image_unmap(pipe, stImage->mt);
1042 stImage->base.Data = NULL;
1043 }
1044}
1045
1046
1047static void
1048st_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
1049 GLenum format, GLenum type, GLvoid * pixels,
1050 struct gl_texture_object *texObj,
1051 struct gl_texture_image *texImage)
1052{
1053 st_get_tex_image(ctx, target, level, format, type, pixels,
1054 texObj, texImage, 0);
1055}
1056
1057
1058static void
1059st_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
1060 GLvoid *pixels,
1061 const struct gl_texture_object *texObj,
1062 const struct gl_texture_image *texImage)
1063{
1064 st_get_tex_image(ctx, target, level, 0, 0, pixels,
1065 (struct gl_texture_object *) texObj,
1066 (struct gl_texture_image *) texImage, 1);
1067}
1068
1069
1070
1071static void
1072st_TexSubimage(GLcontext * ctx,
1073 GLint dims,
1074 GLenum target, GLint level,
1075 GLint xoffset, GLint yoffset, GLint zoffset,
1076 GLint width, GLint height, GLint depth,
1077 GLenum format, GLenum type, const void *pixels,
1078 const struct gl_pixelstore_attrib *packing,
1079 struct gl_texture_object *texObj,
1080 struct gl_texture_image *texImage)
1081{
1082 struct pipe_context *pipe = ctx->st->pipe;
1083 struct st_texture_image *stImage = st_texture_image(texImage);
1084 GLuint dstRowStride;
1085
1086 DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
1087 _mesa_lookup_enum_by_nr(target),
1088 level, xoffset, yoffset, width, height);
1089
1090#if 0
1091 intelFlush(ctx);
1092#endif
1093
1094 pixels =
1095 _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
1096 type, pixels, packing, "glTexSubImage2D");
1097 if (!pixels)
1098 return;
1099
1100 if (stImage->mt)
1101 pipe->region_idle(pipe, stImage->mt->region);
1102
1103#if 0
1104 LOCK_HARDWARE(intel);
1105#endif
1106
1107 /* Map buffer if necessary. Need to lock to prevent other contexts
1108 * from uploading the buffer under us.
1109 */
1110 if (stImage->mt)
1111 texImage->Data = st_miptree_image_map(pipe,
1112 stImage->mt,
1113 stImage->face,
1114 stImage->level,
1115 &dstRowStride,
1116 texImage->ImageOffsets);
1117
1118 assert(dstRowStride);
1119
1120 if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
1121 texImage->TexFormat,
1122 texImage->Data,
1123 xoffset, yoffset, zoffset,
1124 dstRowStride,
1125 texImage->ImageOffsets,
1126 width, height, depth,
1127 format, type, pixels, packing)) {
1128 _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
1129 }
1130
1131#if 0
1132 /* GL_SGIS_generate_mipmap */
1133 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1134 _mesa_generate_mipmap(ctx, target,
1135 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1136 texObj);
1137 }
1138#endif
1139
1140 _mesa_unmap_teximage_pbo(ctx, packing);
1141
1142 if (stImage->mt) {
1143 st_miptree_image_unmap(pipe, stImage->mt);
1144 texImage->Data = NULL;
1145 }
1146
1147#if 0
1148 UNLOCK_HARDWARE(intel);
1149#endif
1150}
1151
1152
1153
1154static void
1155st_TexSubImage3D(GLcontext * ctx,
1156 GLenum target,
1157 GLint level,
1158 GLint xoffset, GLint yoffset, GLint zoffset,
1159 GLsizei width, GLsizei height, GLsizei depth,
1160 GLenum format, GLenum type,
1161 const GLvoid * pixels,
1162 const struct gl_pixelstore_attrib *packing,
1163 struct gl_texture_object *texObj,
1164 struct gl_texture_image *texImage)
1165{
Brianb2458402007-08-07 18:18:54 -06001166 st_TexSubimage(ctx, 3, target, level,
1167 xoffset, yoffset, zoffset,
1168 width, height, depth,
1169 format, type, pixels, packing, texObj, texImage);
Brian24df8f82007-08-06 15:48:42 -06001170}
1171
1172
1173
1174static void
1175st_TexSubImage2D(GLcontext * ctx,
1176 GLenum target,
1177 GLint level,
1178 GLint xoffset, GLint yoffset,
1179 GLsizei width, GLsizei height,
1180 GLenum format, GLenum type,
1181 const GLvoid * pixels,
1182 const struct gl_pixelstore_attrib *packing,
1183 struct gl_texture_object *texObj,
1184 struct gl_texture_image *texImage)
1185{
Brianb2458402007-08-07 18:18:54 -06001186 st_TexSubimage(ctx, 2, target, level,
1187 xoffset, yoffset, 0,
1188 width, height, 1,
1189 format, type, pixels, packing, texObj, texImage);
Brian24df8f82007-08-06 15:48:42 -06001190}
1191
1192
1193static void
1194st_TexSubImage1D(GLcontext * ctx,
1195 GLenum target,
1196 GLint level,
1197 GLint xoffset,
1198 GLsizei width,
1199 GLenum format, GLenum type,
1200 const GLvoid * pixels,
1201 const struct gl_pixelstore_attrib *packing,
1202 struct gl_texture_object *texObj,
1203 struct gl_texture_image *texImage)
1204{
Brianb2458402007-08-07 18:18:54 -06001205 st_TexSubimage(ctx, 1, target, level,
1206 xoffset, 0, 0,
1207 width, 1, 1,
1208 format, type, pixels, packing, texObj, texImage);
Brian24df8f82007-08-06 15:48:42 -06001209}
1210
1211
1212
1213/**
1214 * Get the pipe_region which is the source for any glCopyTex[Sub]Image call.
1215 *
1216 * Do the best we can using the blitter. A future project is to use
1217 * the texture engine and fragment programs for these copies.
1218 */
1219static const struct pipe_region *
1220get_teximage_source(GLcontext *ctx, GLenum internalFormat)
1221{
1222#if 00
1223 struct intel_renderbuffer *irb;
1224
1225 DBG("%s %s\n", __FUNCTION__,
1226 _mesa_lookup_enum_by_nr(internalFormat));
1227
1228 switch (internalFormat) {
1229 case GL_DEPTH_COMPONENT:
1230 case GL_DEPTH_COMPONENT16_ARB:
1231 irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
1232 if (irb && irb->region && irb->region->cpp == 2)
1233 return irb->region;
1234 return NULL;
1235 case GL_DEPTH24_STENCIL8_EXT:
1236 case GL_DEPTH_STENCIL_EXT:
1237 irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
1238 if (irb && irb->region && irb->region->cpp == 4)
1239 return irb->region;
1240 return NULL;
1241 case GL_RGBA:
1242 case GL_RGBA8:
1243 return intel_readbuf_region(intel);
1244 case GL_RGB:
1245 if (intel->intelScreen->front.cpp == 2)
1246 return intel_readbuf_region(intel);
1247 return NULL;
1248 default:
1249 return NULL;
1250 }
1251#else
1252 return NULL;
1253#endif
1254}
1255
1256
1257static GLboolean
1258do_copy_texsubimage(GLcontext *ctx,
1259 struct st_texture_image *stImage,
1260 GLenum internalFormat,
1261 GLint dstx, GLint dsty,
1262 GLint x, GLint y, GLsizei width, GLsizei height)
1263{
1264 const struct pipe_region *src =
1265 get_teximage_source(ctx, internalFormat);
1266
1267 if (!stImage->mt || !src) {
Brian6da92342007-08-06 20:53:28 +01001268 DBG("%s fail %p %p\n", __FUNCTION__, (void *) stImage->mt, (void *) src);
Brian24df8f82007-08-06 15:48:42 -06001269 return GL_FALSE;
1270 }
1271
1272#if 00 /* XXX FIX flush/locking */
1273 intelFlush(ctx);
1274 /* XXX still need the lock ? */
1275 LOCK_HARDWARE(intel);
1276#endif
1277
1278 {
1279 GLuint image_offset = st_miptree_image_offset(stImage->mt,
1280 stImage->face,
1281 stImage->level);
1282 const GLint orig_x = x;
1283 const GLint orig_y = y;
1284 const struct gl_framebuffer *fb = ctx->DrawBuffer;
1285
1286 if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax,
1287 &x, &y, &width, &height)) {
1288 /* Update dst for clipped src. Need to also clip the source rect.
1289 */
1290 dstx += x - orig_x;
1291 dsty += y - orig_y;
1292
1293 if (!(ctx->ReadBuffer->Name == 0)) {
1294 /* XXX this looks bogus ? */
1295 /* FBO: invert Y */
1296 y = ctx->ReadBuffer->Height - y - 1;
1297 }
1298
1299 /* A bit of fiddling to get the blitter to work with -ve
1300 * pitches. But we get a nice inverted blit this way, so it's
1301 * worth it:
1302 */
1303#if 0
1304 intelEmitCopyBlit(intel,
1305 stImage->mt->cpp,
1306 -src->pitch,
1307 src->buffer,
1308 src->height * src->pitch * src->cpp,
1309 stImage->mt->pitch,
1310 stImage->mt->region->buffer,
1311 image_offset,
1312 x, y + height, dstx, dsty, width, height,
1313 GL_COPY); /* ? */
1314 intel_batchbuffer_flush(intel->batch);
1315#else
1316 /* XXX use pipe->region_copy() ??? */
1317 (void) image_offset;
1318#endif
1319 }
1320 }
1321
1322#if 0
1323 UNLOCK_HARDWARE(intel);
1324#endif
1325
1326#if 0
1327 /* GL_SGIS_generate_mipmap -- this can be accelerated now.
1328 * XXX Add a ctx->Driver.GenerateMipmaps() function?
1329 */
1330 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1331 intel_generate_mipmap(ctx, target,
1332 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1333 texObj);
1334 }
1335#endif
1336
1337 return GL_TRUE;
1338}
1339
1340
1341static void
1342st_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
1343 GLenum internalFormat,
1344 GLint x, GLint y, GLsizei width, GLint border)
1345{
1346 struct gl_texture_unit *texUnit =
1347 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1348 struct gl_texture_object *texObj =
1349 _mesa_select_tex_object(ctx, texUnit, target);
1350 struct gl_texture_image *texImage =
1351 _mesa_select_tex_image(ctx, texObj, target, level);
1352
1353 if (border)
1354 goto fail;
1355
1356 /* Setup or redefine the texture object, mipmap tree and texture
1357 * image. Don't populate yet.
1358 */
1359 ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
1360 width, border,
1361 GL_RGBA, CHAN_TYPE, NULL,
1362 &ctx->DefaultPacking, texObj, texImage);
1363
1364 if (!do_copy_texsubimage(ctx,
1365 st_texture_image(texImage),
1366 internalFormat, 0, 0, x, y, width, 1))
1367 goto fail;
1368
1369 return;
1370
1371 fail:
1372#if 0
1373 _swrast_copy_teximage1d(ctx, target, level, internalFormat, x, y,
1374 width, border);
1375#endif
1376 ;
1377}
1378
1379
1380static void
1381st_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1382 GLenum internalFormat,
1383 GLint x, GLint y, GLsizei width, GLsizei height,
1384 GLint border)
1385{
1386 struct gl_texture_unit *texUnit =
1387 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1388 struct gl_texture_object *texObj =
1389 _mesa_select_tex_object(ctx, texUnit, target);
1390 struct gl_texture_image *texImage =
1391 _mesa_select_tex_image(ctx, texObj, target, level);
1392
1393 if (border)
1394 goto fail;
1395
1396 /* Setup or redefine the texture object, mipmap tree and texture
1397 * image. Don't populate yet.
1398 */
1399 ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
1400 width, height, border,
1401 GL_RGBA, CHAN_TYPE, NULL,
1402 &ctx->DefaultPacking, texObj, texImage);
1403
1404
1405 if (!do_copy_texsubimage(ctx,
1406 st_texture_image(texImage),
1407 internalFormat, 0, 0, x, y, width, height))
1408 goto fail;
1409
1410 return;
1411
1412 fail:
1413#if 0
1414 _swrast_copy_teximage2d(ctx, target, level, internalFormat, x, y,
1415 width, height, border);
1416#endif
1417 assert(0);
1418}
1419
1420
1421static void
1422st_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
1423 GLint xoffset, GLint x, GLint y, GLsizei width)
1424{
1425 struct gl_texture_unit *texUnit =
1426 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1427 struct gl_texture_object *texObj =
1428 _mesa_select_tex_object(ctx, texUnit, target);
1429 struct gl_texture_image *texImage =
1430 _mesa_select_tex_image(ctx, texObj, target, level);
1431 GLenum internalFormat = texImage->InternalFormat;
1432
1433 /* XXX need to check <border> as in above function? */
1434
1435 /* Need to check texture is compatible with source format.
1436 */
1437
1438 if (!do_copy_texsubimage(ctx,
1439 st_texture_image(texImage),
1440 internalFormat, xoffset, 0, x, y, width, 1)) {
1441#if 0
1442 _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width);
1443#endif
1444 assert(0);
1445 }
1446}
1447
1448
1449static void
1450st_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1451 GLint xoffset, GLint yoffset,
1452 GLint x, GLint y, GLsizei width, GLsizei height)
1453{
1454 struct gl_texture_unit *texUnit =
1455 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1456 struct gl_texture_object *texObj =
1457 _mesa_select_tex_object(ctx, texUnit, target);
1458 struct gl_texture_image *texImage =
1459 _mesa_select_tex_image(ctx, texObj, target, level);
1460 GLenum internalFormat = texImage->InternalFormat;
1461
1462
1463 /* Need to check texture is compatible with source format.
1464 */
1465
1466 if (!do_copy_texsubimage(ctx,
1467 st_texture_image(texImage),
1468 internalFormat,
1469 xoffset, yoffset, x, y, width, height)) {
1470#if 0
1471 _swrast_copy_texsubimage2d(ctx, target, level,
1472 xoffset, yoffset, x, y, width, height);
1473#endif
1474 assert(0);
1475 }
1476}
1477
1478
1479
1480
1481/**
1482 * Compute which mipmap levels that really need to be sent to the hardware.
1483 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
1484 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
1485 */
1486static void
Brian14b98342007-08-07 16:42:08 -06001487calculate_first_last_level(struct st_texture_object *stObj)
Brian24df8f82007-08-06 15:48:42 -06001488{
Brian14b98342007-08-07 16:42:08 -06001489 struct gl_texture_object *tObj = &stObj->base;
Brian24df8f82007-08-06 15:48:42 -06001490 const struct gl_texture_image *const baseImage =
1491 tObj->Image[0][tObj->BaseLevel];
1492
1493 /* These must be signed values. MinLod and MaxLod can be negative numbers,
1494 * and having firstLevel and lastLevel as signed prevents the need for
1495 * extra sign checks.
1496 */
1497 int firstLevel;
1498 int lastLevel;
1499
1500 /* Yes, this looks overly complicated, but it's all needed.
1501 */
1502 switch (tObj->Target) {
1503 case GL_TEXTURE_1D:
1504 case GL_TEXTURE_2D:
1505 case GL_TEXTURE_3D:
1506 case GL_TEXTURE_CUBE_MAP:
1507 if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
1508 /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
1509 */
1510 firstLevel = lastLevel = tObj->BaseLevel;
1511 }
1512 else {
1513 firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
1514 firstLevel = MAX2(firstLevel, tObj->BaseLevel);
1515 lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
1516 lastLevel = MAX2(lastLevel, tObj->BaseLevel);
1517 lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
1518 lastLevel = MIN2(lastLevel, tObj->MaxLevel);
1519 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
1520 }
1521 break;
1522 case GL_TEXTURE_RECTANGLE_NV:
1523 case GL_TEXTURE_4D_SGIS:
1524 firstLevel = lastLevel = 0;
1525 break;
1526 default:
1527 return;
1528 }
1529
1530 /* save these values */
Brian14b98342007-08-07 16:42:08 -06001531 stObj->firstLevel = firstLevel;
1532 stObj->lastLevel = lastLevel;
Brian24df8f82007-08-06 15:48:42 -06001533}
1534
1535
1536static void
1537copy_image_data_to_tree(struct pipe_context *pipe,
Brian14b98342007-08-07 16:42:08 -06001538 struct st_texture_object *stObj,
Brian24df8f82007-08-06 15:48:42 -06001539 struct st_texture_image *stImage)
1540{
1541 if (stImage->mt) {
1542 /* Copy potentially with the blitter:
1543 */
1544 st_miptree_image_copy(pipe,
Brian14b98342007-08-07 16:42:08 -06001545 stObj->mt,
Brian24df8f82007-08-06 15:48:42 -06001546 stImage->face,
1547 stImage->level, stImage->mt);
1548
1549 st_miptree_release(pipe, &stImage->mt);
1550 }
1551 else {
1552 assert(stImage->base.Data != NULL);
1553
1554 /* More straightforward upload.
1555 */
1556 st_miptree_image_data(pipe,
Brian14b98342007-08-07 16:42:08 -06001557 stObj->mt,
Brian24df8f82007-08-06 15:48:42 -06001558 stImage->face,
1559 stImage->level,
1560 stImage->base.Data,
1561 stImage->base.RowStride,
1562 stImage->base.RowStride *
1563 stImage->base.Height);
1564 _mesa_align_free(stImage->base.Data);
1565 stImage->base.Data = NULL;
1566 }
1567
Brian14b98342007-08-07 16:42:08 -06001568 st_miptree_reference(&stImage->mt, stObj->mt);
Brian24df8f82007-08-06 15:48:42 -06001569}
1570
1571
1572/*
1573 */
Brian14b98342007-08-07 16:42:08 -06001574GLboolean
Brian24df8f82007-08-06 15:48:42 -06001575st_finalize_mipmap_tree(GLcontext *ctx,
1576 struct pipe_context *pipe, GLuint unit,
1577 GLboolean *needFlush)
1578{
1579 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
Brian14b98342007-08-07 16:42:08 -06001580 struct st_texture_object *stObj = st_texture_object(tObj);
Brian24df8f82007-08-06 15:48:42 -06001581 int comp_byte = 0;
1582 int cpp;
1583
1584 GLuint face, i;
1585 GLuint nr_faces = 0;
1586 struct st_texture_image *firstImage;
1587
1588 *needFlush = GL_FALSE;
1589
1590 /* We know/require this is true by now:
1591 */
Brian14b98342007-08-07 16:42:08 -06001592 assert(stObj->base._Complete);
Brian24df8f82007-08-06 15:48:42 -06001593
1594 /* What levels must the tree include at a minimum?
1595 */
Brian14b98342007-08-07 16:42:08 -06001596 calculate_first_last_level(stObj);
Brian24df8f82007-08-06 15:48:42 -06001597 firstImage =
Brian14b98342007-08-07 16:42:08 -06001598 st_texture_image(stObj->base.Image[0][stObj->firstLevel]);
Brian24df8f82007-08-06 15:48:42 -06001599
1600 /* Fallback case:
1601 */
1602 if (firstImage->base.Border) {
Brian14b98342007-08-07 16:42:08 -06001603 if (stObj->mt) {
1604 st_miptree_release(pipe, &stObj->mt);
Brian24df8f82007-08-06 15:48:42 -06001605 }
1606 return GL_FALSE;
1607 }
1608
1609
Brian14b98342007-08-07 16:42:08 -06001610 /* If both firstImage and stObj have a tree which can contain
Brian24df8f82007-08-06 15:48:42 -06001611 * all active images, favour firstImage. Note that because of the
1612 * completeness requirement, we know that the image dimensions
1613 * will match.
1614 */
1615 if (firstImage->mt &&
Brian14b98342007-08-07 16:42:08 -06001616 firstImage->mt != stObj->mt &&
1617 firstImage->mt->first_level <= stObj->firstLevel &&
1618 firstImage->mt->last_level >= stObj->lastLevel) {
Brian24df8f82007-08-06 15:48:42 -06001619
Brian14b98342007-08-07 16:42:08 -06001620 if (stObj->mt)
1621 st_miptree_release(pipe, &stObj->mt);
Brian24df8f82007-08-06 15:48:42 -06001622
Brian14b98342007-08-07 16:42:08 -06001623 st_miptree_reference(&stObj->mt, firstImage->mt);
Brian24df8f82007-08-06 15:48:42 -06001624 }
1625
1626 if (firstImage->base.IsCompressed) {
Brian14b98342007-08-07 16:42:08 -06001627 comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
Brian24df8f82007-08-06 15:48:42 -06001628 cpp = comp_byte;
1629 }
1630 else cpp = firstImage->base.TexFormat->TexelBytes;
1631
1632 /* Check tree can hold all active levels. Check tree matches
1633 * target, imageFormat, etc.
1634 *
1635 * XXX: For some layouts (eg i945?), the test might have to be
1636 * first_level == firstLevel, as the tree isn't valid except at the
1637 * original start level. Hope to get around this by
1638 * programming minLod, maxLod, baseLevel into the hardware and
1639 * leaving the tree alone.
1640 */
Brian14b98342007-08-07 16:42:08 -06001641 if (stObj->mt &&
1642 (stObj->mt->target != stObj->base.Target ||
1643 stObj->mt->internal_format != firstImage->base.InternalFormat ||
1644 stObj->mt->first_level != stObj->firstLevel ||
1645 stObj->mt->last_level != stObj->lastLevel ||
1646 stObj->mt->width0 != firstImage->base.Width ||
1647 stObj->mt->height0 != firstImage->base.Height ||
1648 stObj->mt->depth0 != firstImage->base.Depth ||
1649 stObj->mt->cpp != cpp ||
1650 stObj->mt->compressed != firstImage->base.IsCompressed)) {
1651 st_miptree_release(pipe, &stObj->mt);
Brian24df8f82007-08-06 15:48:42 -06001652 }
1653
1654
1655 /* May need to create a new tree:
1656 */
Brian14b98342007-08-07 16:42:08 -06001657 if (!stObj->mt) {
1658 stObj->mt = st_miptree_create(pipe,
Brianb2458402007-08-07 18:18:54 -06001659 stObj->base.Target,
1660 firstImage->base.InternalFormat,
1661 stObj->firstLevel,
1662 stObj->lastLevel,
1663 firstImage->base.Width,
1664 firstImage->base.Height,
1665 firstImage->base.Depth,
1666 cpp,
1667 comp_byte);
1668
1669 stObj->mt->format
1670 = mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
Brian24df8f82007-08-06 15:48:42 -06001671 }
1672
1673 /* Pull in any images not in the object's tree:
1674 */
Brian14b98342007-08-07 16:42:08 -06001675 nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
Brian24df8f82007-08-06 15:48:42 -06001676 for (face = 0; face < nr_faces; face++) {
Brian14b98342007-08-07 16:42:08 -06001677 for (i = stObj->firstLevel; i <= stObj->lastLevel; i++) {
Brian24df8f82007-08-06 15:48:42 -06001678 struct st_texture_image *stImage =
Brian14b98342007-08-07 16:42:08 -06001679 st_texture_image(stObj->base.Image[face][i]);
Brian24df8f82007-08-06 15:48:42 -06001680
1681 /* Need to import images in main memory or held in other trees.
1682 */
Brian14b98342007-08-07 16:42:08 -06001683 if (stObj->mt != stImage->mt) {
1684 copy_image_data_to_tree(pipe, stObj, stImage);
Brian24df8f82007-08-06 15:48:42 -06001685 *needFlush = GL_TRUE;
1686 }
1687 }
1688 }
1689
1690 /**
1691 if (need_flush)
1692 intel_batchbuffer_flush(intel->batch);
1693 **/
1694
1695 return GL_TRUE;
1696}
1697
1698
1699#if 0 /* unused? */
1700void
1701st_tex_map_images(struct pipe_context *pipe,
Brian14b98342007-08-07 16:42:08 -06001702 struct st_texture_object *stObj)
Brian24df8f82007-08-06 15:48:42 -06001703{
Brian14b98342007-08-07 16:42:08 -06001704 GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
Brian24df8f82007-08-06 15:48:42 -06001705 GLuint face, i;
1706
1707 DBG("%s\n", __FUNCTION__);
1708
1709 for (face = 0; face < nr_faces; face++) {
Brian14b98342007-08-07 16:42:08 -06001710 for (i = stObj->firstLevel; i <= stObj->lastLevel; i++) {
Brian24df8f82007-08-06 15:48:42 -06001711 struct st_texture_image *stImage =
Brian14b98342007-08-07 16:42:08 -06001712 st_texture_image(stObj->base.Image[face][i]);
Brian24df8f82007-08-06 15:48:42 -06001713
1714 if (stImage->mt) {
Brianb2458402007-08-07 18:18:54 -06001715 stImage->base.Data
1716 = st_miptree_image_map(pipe,
1717 stImage->mt,
1718 stImage->face,
1719 stImage->level,
1720 &stImage->base.RowStride,
1721 stImage->base.ImageOffsets);
Brian24df8f82007-08-06 15:48:42 -06001722 /* convert stride to texels, not bytes */
1723 stImage->base.RowStride /= stImage->mt->cpp;
1724/* stImage->base.ImageStride /= stImage->mt->cpp; */
1725 }
1726 }
1727 }
1728}
1729
1730
1731
1732void
1733st_tex_unmap_images(struct pipe_context *pipe,
Brian14b98342007-08-07 16:42:08 -06001734 struct st_texture_object *stObj)
Brian24df8f82007-08-06 15:48:42 -06001735{
Brian14b98342007-08-07 16:42:08 -06001736 GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
Brian24df8f82007-08-06 15:48:42 -06001737 GLuint face, i;
1738
1739 for (face = 0; face < nr_faces; face++) {
Brian14b98342007-08-07 16:42:08 -06001740 for (i = stObj->firstLevel; i <= stObj->lastLevel; i++) {
Brian24df8f82007-08-06 15:48:42 -06001741 struct st_texture_image *stImage =
Brian14b98342007-08-07 16:42:08 -06001742 st_texture_image(stObj->base.Image[face][i]);
Brian24df8f82007-08-06 15:48:42 -06001743
1744 if (stImage->mt) {
1745 st_miptree_image_unmap(pipe, stImage->mt);
1746 stImage->base.Data = NULL;
1747 }
1748 }
1749 }
1750}
1751#endif
1752
1753
1754
1755
Brian6da92342007-08-06 20:53:28 +01001756void
1757st_init_texture_functions(struct dd_function_table *functions)
Brian24df8f82007-08-06 15:48:42 -06001758{
Brian24df8f82007-08-06 15:48:42 -06001759 functions->ChooseTextureFormat = st_ChooseTextureFormat;
1760 functions->TexImage1D = st_TexImage1D;
1761 functions->TexImage2D = st_TexImage2D;
1762 functions->TexImage3D = st_TexImage3D;
1763 functions->TexSubImage1D = st_TexSubImage1D;
1764 functions->TexSubImage2D = st_TexSubImage2D;
1765 functions->TexSubImage3D = st_TexSubImage3D;
1766 functions->CopyTexImage1D = st_CopyTexImage1D;
1767 functions->CopyTexImage2D = st_CopyTexImage2D;
1768 functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
1769 functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
1770 functions->GetTexImage = st_GetTexImage;
1771
1772 /* compressed texture functions */
1773 functions->CompressedTexImage2D = st_CompressedTexImage2D;
1774 functions->GetCompressedTexImage = st_GetCompressedTexImage;
1775
1776 functions->NewTextureObject = st_NewTextureObject;
1777 functions->NewTextureImage = st_NewTextureImage;
1778 functions->DeleteTexture = st_DeleteTextureObject;
1779 functions->FreeTexImageData = st_FreeTextureImageData;
1780 functions->UpdateTexturePalette = 0;
1781 functions->IsTextureResident = st_IsTextureResident;
1782
1783 functions->TextureMemCpy = do_memcpy;
1784}