intel_tex_image.c revision dcb4716802878690908a101b1c196737851d4151
1
2#include "main/glheader.h"
3#include "main/macros.h"
4#include "main/mtypes.h"
5#include "main/enums.h"
6#include "main/bufferobj.h"
7#include "main/convolve.h"
8#include "main/context.h"
9#include "main/image.h"
10#include "main/texcompress.h"
11#include "main/texstore.h"
12#include "main/texgetimage.h"
13#include "main/texobj.h"
14#include "main/texstore.h"
15#include "main/teximage.h"
16
17#include "intel_context.h"
18#include "intel_mipmap_tree.h"
19#include "intel_buffer_objects.h"
20#include "intel_batchbuffer.h"
21#include "intel_tex.h"
22#include "intel_blit.h"
23#include "intel_fbo.h"
24
25#define FILE_DEBUG_FLAG DEBUG_TEXTURE
26
27/* Functions to store texture images.  Where possible, mipmap_tree's
28 * will be created or further instantiated with image data, otherwise
29 * images will be stored in malloc'd memory.  A validation step is
30 * required to pull those images into a mipmap tree, or otherwise
31 * decide a fallback is required.
32 */
33
34
35static int
36logbase2(int n)
37{
38   GLint i = 1;
39   GLint log2 = 0;
40
41   while (n > i) {
42      i *= 2;
43      log2++;
44   }
45
46   return log2;
47}
48
49
50/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
51 * 1).
52 *
53 * Otherwise, if max_level >= level >= min_level, create tree with
54 * space for textures from min_level down to max_level.
55 *
56 * Otherwise, create tree with space for textures from (level
57 * 0)..(1x1).  Consider pruning this tree at a validation if the
58 * saving is worth it.
59 */
60static void
61guess_and_alloc_mipmap_tree(struct intel_context *intel,
62                            struct intel_texture_object *intelObj,
63                            struct intel_texture_image *intelImage,
64			    GLboolean expect_accelerated_upload)
65{
66   GLuint firstLevel;
67   GLuint lastLevel;
68   GLuint width = intelImage->base.Width;
69   GLuint height = intelImage->base.Height;
70   GLuint depth = intelImage->base.Depth;
71   GLuint l2width, l2height, l2depth;
72   GLuint i, comp_byte = 0;
73   GLuint texelBytes;
74
75   DBG("%s\n", __FUNCTION__);
76
77   if (intelImage->base.Border ||
78       ((intelImage->base._BaseFormat == GL_DEPTH_COMPONENT) &&
79        ((intelObj->base.WrapS == GL_CLAMP_TO_BORDER) ||
80         (intelObj->base.WrapT == GL_CLAMP_TO_BORDER))))
81      return;
82
83   if (intelImage->level > intelObj->base.BaseLevel &&
84       (intelImage->base.Width == 1 ||
85        (intelObj->base.Target != GL_TEXTURE_1D &&
86         intelImage->base.Height == 1) ||
87        (intelObj->base.Target == GL_TEXTURE_3D &&
88         intelImage->base.Depth == 1)))
89      return;
90
91   /* If this image disrespects BaseLevel, allocate from level zero.
92    * Usually BaseLevel == 0, so it's unlikely to happen.
93    */
94   if (intelImage->level < intelObj->base.BaseLevel)
95      firstLevel = 0;
96   else
97      firstLevel = intelObj->base.BaseLevel;
98
99
100   /* Figure out image dimensions at start level.
101    */
102   for (i = intelImage->level; i > firstLevel; i--) {
103      width <<= 1;
104      if (height != 1)
105         height <<= 1;
106      if (depth != 1)
107         depth <<= 1;
108   }
109
110   /* Guess a reasonable value for lastLevel.  This is probably going
111    * to be wrong fairly often and might mean that we have to look at
112    * resizable buffers, or require that buffers implement lazy
113    * pagetable arrangements.
114    */
115   if ((intelObj->base.MinFilter == GL_NEAREST ||
116        intelObj->base.MinFilter == GL_LINEAR) &&
117       intelImage->level == firstLevel) {
118      lastLevel = firstLevel;
119   }
120   else {
121      l2width = logbase2(width);
122      l2height = logbase2(height);
123      l2depth = logbase2(depth);
124      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
125   }
126
127   assert(!intelObj->mt);
128   if (_mesa_is_format_compressed(intelImage->base.TexFormat))
129      comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat);
130
131   texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
132
133   intelObj->mt = intel_miptree_create(intel,
134                                       intelObj->base.Target,
135                                       intelImage->base._BaseFormat,
136                                       intelImage->base.InternalFormat,
137                                       firstLevel,
138                                       lastLevel,
139                                       width,
140                                       height,
141                                       depth,
142                                       texelBytes,
143                                       comp_byte,
144				       expect_accelerated_upload);
145
146   DBG("%s - success\n", __FUNCTION__);
147}
148
149
150
151
152static GLuint
153target_to_face(GLenum target)
154{
155   switch (target) {
156   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
157   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
158   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
159   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
160   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
161   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
162      return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
163   default:
164      return 0;
165   }
166}
167
168/* There are actually quite a few combinations this will work for,
169 * more than what I've listed here.
170 */
171static GLboolean
172check_pbo_format(GLint internalFormat,
173                 GLenum format, GLenum type,
174                 gl_format mesa_format)
175{
176   switch (internalFormat) {
177   case 4:
178   case GL_RGBA:
179      return (format == GL_BGRA &&
180              (type == GL_UNSIGNED_BYTE ||
181               type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
182              mesa_format == MESA_FORMAT_ARGB8888);
183   case 3:
184   case GL_RGB:
185      return (format == GL_RGB &&
186              type == GL_UNSIGNED_SHORT_5_6_5 &&
187              mesa_format == MESA_FORMAT_RGB565);
188   case GL_YCBCR_MESA:
189      return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE);
190   default:
191      return GL_FALSE;
192   }
193}
194
195
196/* XXX: Do this for TexSubImage also:
197 */
198static GLboolean
199try_pbo_upload(struct intel_context *intel,
200               struct intel_texture_image *intelImage,
201               const struct gl_pixelstore_attrib *unpack,
202               GLint internalFormat,
203               GLint width, GLint height,
204               GLenum format, GLenum type, const void *pixels)
205{
206   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
207   GLuint src_offset, src_stride;
208   GLuint dst_x, dst_y, dst_stride;
209   dri_bo *dst_buffer = intel_region_buffer(intel,
210					    intelImage->mt->region,
211					    INTEL_WRITE_FULL);
212
213   if (!_mesa_is_bufferobj(unpack->BufferObj) ||
214       intel->ctx._ImageTransferState ||
215       unpack->SkipPixels || unpack->SkipRows) {
216      DBG("%s: failure 1\n", __FUNCTION__);
217      return GL_FALSE;
218   }
219
220   /* note: potential 64-bit ptr to 32-bit int cast */
221   src_offset = (GLuint) (unsigned long) pixels;
222
223   if (unpack->RowLength > 0)
224      src_stride = unpack->RowLength;
225   else
226      src_stride = width;
227
228   intel_miptree_get_image_offset(intelImage->mt, intelImage->level,
229				  intelImage->face, 0,
230				  &dst_x, &dst_y);
231
232   dst_stride = intelImage->mt->pitch;
233
234   if (drm_intel_bo_references(intel->batch->buf, dst_buffer))
235      intelFlush(&intel->ctx);
236   LOCK_HARDWARE(intel);
237   {
238      dri_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ);
239
240      if (!intelEmitCopyBlit(intel,
241			     intelImage->mt->cpp,
242			     src_stride, src_buffer, src_offset, GL_FALSE,
243			     dst_stride, dst_buffer, 0, GL_FALSE,
244			     0, 0, dst_x, dst_y, width, height,
245			     GL_COPY)) {
246	 UNLOCK_HARDWARE(intel);
247	 return GL_FALSE;
248      }
249   }
250   UNLOCK_HARDWARE(intel);
251
252   return GL_TRUE;
253}
254
255
256static GLboolean
257try_pbo_zcopy(struct intel_context *intel,
258              struct intel_texture_image *intelImage,
259              const struct gl_pixelstore_attrib *unpack,
260              GLint internalFormat,
261              GLint width, GLint height,
262              GLenum format, GLenum type, const void *pixels)
263{
264   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
265   GLuint src_offset, src_stride;
266   GLuint dst_x, dst_y, dst_stride;
267
268   if (!_mesa_is_bufferobj(unpack->BufferObj) ||
269       intel->ctx._ImageTransferState ||
270       unpack->SkipPixels || unpack->SkipRows) {
271      DBG("%s: failure 1\n", __FUNCTION__);
272      return GL_FALSE;
273   }
274
275   /* note: potential 64-bit ptr to 32-bit int cast */
276   src_offset = (GLuint) (unsigned long) pixels;
277
278   if (unpack->RowLength > 0)
279      src_stride = unpack->RowLength;
280   else
281      src_stride = width;
282
283   intel_miptree_get_image_offset(intelImage->mt, intelImage->level,
284				  intelImage->face, 0,
285				  &dst_x, &dst_y);
286
287   dst_stride = intelImage->mt->pitch;
288
289   if (src_stride != dst_stride || dst_x != 0 || dst_y != 0 ||
290       src_offset != 0) {
291      DBG("%s: failure 2\n", __FUNCTION__);
292      return GL_FALSE;
293   }
294
295   intel_region_attach_pbo(intel, intelImage->mt->region, pbo);
296
297   return GL_TRUE;
298}
299
300
301static void
302intelTexImage(GLcontext * ctx,
303              GLint dims,
304              GLenum target, GLint level,
305              GLint internalFormat,
306              GLint width, GLint height, GLint depth,
307              GLint border,
308              GLenum format, GLenum type, const void *pixels,
309              const struct gl_pixelstore_attrib *unpack,
310              struct gl_texture_object *texObj,
311              struct gl_texture_image *texImage, GLsizei imageSize,
312              GLboolean compressed)
313{
314   struct intel_context *intel = intel_context(ctx);
315   struct intel_texture_object *intelObj = intel_texture_object(texObj);
316   struct intel_texture_image *intelImage = intel_texture_image(texImage);
317   GLint postConvWidth = width;
318   GLint postConvHeight = height;
319   GLint texelBytes, sizeInBytes;
320   GLuint dstRowStride = 0, srcRowStride = texImage->RowStride;
321
322   DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
323       _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
324
325   intelImage->face = target_to_face(target);
326   intelImage->level = level;
327
328   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
329      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
330                                         &postConvHeight);
331   }
332
333   if (_mesa_is_format_compressed(texImage->TexFormat)) {
334      texelBytes = 0;
335   }
336   else {
337      texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
338
339      /* Minimum pitch of 32 bytes */
340      if (postConvWidth * texelBytes < 32) {
341	 postConvWidth = 32 / texelBytes;
342	 texImage->RowStride = postConvWidth;
343      }
344
345      if (!intelImage->mt) {
346	  assert(texImage->RowStride == postConvWidth);
347      }
348   }
349
350   /* Release the reference to a potentially orphaned buffer.
351    * Release any old malloced memory.
352    */
353   if (intelImage->mt) {
354      intel_miptree_release(intel, &intelImage->mt);
355      assert(!texImage->Data);
356   }
357   else if (texImage->Data) {
358      _mesa_free_texmemory(texImage->Data);
359      texImage->Data = NULL;
360   }
361
362   /* If this is the only texture image in the tree, could call
363    * bmBufferData with NULL data to free the old block and avoid
364    * waiting on any outstanding fences.
365    */
366   if (intelObj->mt &&
367       intelObj->mt->first_level == level &&
368       intelObj->mt->last_level == level &&
369       intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
370       !intel_miptree_match_image(intelObj->mt, &intelImage->base,
371                                  intelImage->face, intelImage->level)) {
372
373      DBG("release it\n");
374      intel_miptree_release(intel, &intelObj->mt);
375      assert(!intelObj->mt);
376   }
377
378   if (!intelObj->mt) {
379      guess_and_alloc_mipmap_tree(intel, intelObj, intelImage, pixels == NULL);
380      if (!intelObj->mt) {
381	 DBG("guess_and_alloc_mipmap_tree: failed\n");
382      }
383   }
384
385   assert(!intelImage->mt);
386
387   if (intelObj->mt &&
388       intel_miptree_match_image(intelObj->mt, &intelImage->base,
389                                 intelImage->face, intelImage->level)) {
390
391      intel_miptree_reference(&intelImage->mt, intelObj->mt);
392      assert(intelImage->mt);
393   } else if (intelImage->base.Border == 0) {
394      int comp_byte = 0;
395      GLuint texelBytes = _mesa_get_format_bytes(intelImage->base.TexFormat);
396      GLenum baseFormat = _mesa_get_format_base_format(intelImage->base.TexFormat);
397      if (_mesa_is_format_compressed(intelImage->base.TexFormat)) {
398	 comp_byte =
399	    intel_compressed_num_bytes(intelImage->base.TexFormat);
400      }
401
402      /* Didn't fit in the object miptree, but it's suitable for inclusion in
403       * a miptree, so create one just for our level and store it in the image.
404       * It'll get moved into the object miptree at validate time.
405       */
406      intelImage->mt = intel_miptree_create(intel, target,
407					    baseFormat,
408					    internalFormat,
409					    level, level,
410					    width, height, depth,
411					    texelBytes,
412					    comp_byte, pixels == NULL);
413
414   }
415
416   /* PBO fastpaths:
417    */
418   if (dims <= 2 &&
419       intelImage->mt &&
420       _mesa_is_bufferobj(unpack->BufferObj) &&
421       check_pbo_format(internalFormat, format,
422                        type, intelImage->base.TexFormat)) {
423
424      DBG("trying pbo upload\n");
425
426      /* Attempt to texture directly from PBO data (zero copy upload).
427       *
428       * Currently disable as it can lead to worse as well as better
429       * performance (in particular when intel_region_cow() is
430       * required).
431       */
432      if (intelObj->mt == intelImage->mt &&
433          intelObj->mt->first_level == level &&
434          intelObj->mt->last_level == level) {
435
436         if (try_pbo_zcopy(intel, intelImage, unpack,
437                           internalFormat,
438                           width, height, format, type, pixels)) {
439
440            DBG("pbo zcopy upload succeeded\n");
441            return;
442         }
443      }
444
445
446      /* Otherwise, attempt to use the blitter for PBO image uploads.
447       */
448      if (try_pbo_upload(intel, intelImage, unpack,
449                         internalFormat,
450                         width, height, format, type, pixels)) {
451         DBG("pbo upload succeeded\n");
452         return;
453      }
454
455      DBG("pbo upload failed\n");
456   }
457
458   /* intelCopyTexImage calls this function with pixels == NULL, with
459    * the expectation that the mipmap tree will be set up but nothing
460    * more will be done.  This is where those calls return:
461    */
462   if (compressed) {
463      pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
464						      unpack,
465						      "glCompressedTexImage");
466   } else {
467      pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
468					   format, type,
469					   pixels, unpack, "glTexImage");
470   }
471
472   LOCK_HARDWARE(intel);
473
474   if (intelImage->mt) {
475      if (pixels != NULL) {
476	 /* Flush any queued rendering with the texture before mapping. */
477	 if (drm_intel_bo_references(intel->batch->buf,
478				     intelImage->mt->region->buffer)) {
479	    intelFlush(ctx);
480	 }
481         texImage->Data = intel_miptree_image_map(intel,
482                                                  intelImage->mt,
483                                                  intelImage->face,
484                                                  intelImage->level,
485                                                  &dstRowStride,
486                                                  intelImage->base.ImageOffsets);
487      }
488
489      texImage->RowStride = dstRowStride / intelImage->mt->cpp;
490   }
491   else {
492      /* Allocate regular memory and store the image there temporarily.   */
493      if (_mesa_is_format_compressed(texImage->TexFormat)) {
494         sizeInBytes = _mesa_format_image_size(texImage->TexFormat,
495                                               texImage->Width,
496                                               texImage->Height,
497                                               texImage->Depth);
498         dstRowStride =
499            _mesa_format_row_stride(texImage->TexFormat, width);
500         assert(dims != 3);
501      }
502      else {
503         dstRowStride = postConvWidth * texelBytes;
504         sizeInBytes = depth * dstRowStride * postConvHeight;
505      }
506
507      texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
508   }
509
510   DBG("Upload image %dx%dx%d row_len %d "
511       "pitch %d pixels %d compressed %d\n",
512       width, height, depth, width * texelBytes, dstRowStride,
513       pixels ? 1 : 0, compressed);
514
515   /* Copy data.  Would like to know when it's ok for us to eg. use
516    * the blitter to copy.  Or, use the hardware to do the format
517    * conversion and copy:
518    */
519   if (pixels) {
520       if (compressed) {
521	   if (intelImage->mt) {
522	       struct intel_region *dst = intelImage->mt->region;
523	       _mesa_copy_rect(texImage->Data, dst->cpp, dst->pitch,
524			       0, 0,
525			       intelImage->mt->level[level].width,
526			       (intelImage->mt->level[level].height+3)/4,
527			       pixels,
528			       srcRowStride,
529			       0, 0);
530	   }
531           else {
532	       memcpy(texImage->Data, pixels, imageSize);
533           }
534       }
535       else if (!_mesa_texstore(ctx, dims,
536                                texImage->_BaseFormat,
537                                texImage->TexFormat,
538                                texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
539                                dstRowStride,
540                                texImage->ImageOffsets,
541                                width, height, depth,
542                                format, type, pixels, unpack)) {
543          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
544       }
545   }
546
547   _mesa_unmap_teximage_pbo(ctx, unpack);
548
549   if (intelImage->mt) {
550      if (pixels != NULL)
551         intel_miptree_image_unmap(intel, intelImage->mt);
552      texImage->Data = NULL;
553   }
554
555   UNLOCK_HARDWARE(intel);
556}
557
558
559static void
560intelTexImage3D(GLcontext * ctx,
561                GLenum target, GLint level,
562                GLint internalFormat,
563                GLint width, GLint height, GLint depth,
564                GLint border,
565                GLenum format, GLenum type, const void *pixels,
566                const struct gl_pixelstore_attrib *unpack,
567                struct gl_texture_object *texObj,
568                struct gl_texture_image *texImage)
569{
570   intelTexImage(ctx, 3, target, level,
571                 internalFormat, width, height, depth, border,
572                 format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
573}
574
575
576static void
577intelTexImage2D(GLcontext * ctx,
578                GLenum target, GLint level,
579                GLint internalFormat,
580                GLint width, GLint height, GLint border,
581                GLenum format, GLenum type, const void *pixels,
582                const struct gl_pixelstore_attrib *unpack,
583                struct gl_texture_object *texObj,
584                struct gl_texture_image *texImage)
585{
586   intelTexImage(ctx, 2, target, level,
587                 internalFormat, width, height, 1, border,
588                 format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
589}
590
591
592static void
593intelTexImage1D(GLcontext * ctx,
594                GLenum target, GLint level,
595                GLint internalFormat,
596                GLint width, GLint border,
597                GLenum format, GLenum type, const void *pixels,
598                const struct gl_pixelstore_attrib *unpack,
599                struct gl_texture_object *texObj,
600                struct gl_texture_image *texImage)
601{
602   intelTexImage(ctx, 1, target, level,
603                 internalFormat, width, 1, 1, border,
604                 format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
605}
606
607
608static void
609intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
610                           GLint internalFormat,
611                           GLint width, GLint height, GLint border,
612                           GLsizei imageSize, const GLvoid *data,
613                           struct gl_texture_object *texObj,
614                           struct gl_texture_image *texImage )
615{
616   intelTexImage(ctx, 2, target, level,
617		 internalFormat, width, height, 1, border,
618		 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE);
619}
620
621
622/**
623 * Try to use memcpy() to do a glGetTexImage().
624 * \return GL_TRUE if done, GL_FALSE otherwise
625 */
626static GLboolean
627memcpy_get_tex_image(GLcontext *ctx, GLenum target, GLint level,
628                     GLenum format, GLenum type, GLvoid * pixels,
629                     struct gl_texture_object *texObj,
630                     struct gl_texture_image *texImage)
631{
632   GLboolean memCopy = GL_FALSE;
633
634   /* Texture image should have been mapped already */
635   assert(texImage->Data);
636
637   /*
638    * Check if the src/dst formats are compatible.
639    * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
640    * so we don't have to worry about those.
641    */
642   if ((texObj->Target == GL_TEXTURE_1D ||
643        texObj->Target == GL_TEXTURE_2D ||
644        texObj->Target == GL_TEXTURE_RECTANGLE ||
645        (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
646         texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
647      if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
648          format == GL_BGRA &&
649          type == GL_UNSIGNED_BYTE &&
650          _mesa_little_endian()) {
651         memCopy = GL_TRUE;
652      }
653      else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
654               format == GL_LUMINANCE_ALPHA &&
655               type == GL_UNSIGNED_BYTE &&
656               _mesa_little_endian()) {
657         memCopy = GL_TRUE;
658      }
659      else if (texImage->TexFormat == MESA_FORMAT_L8 &&
660               format == GL_LUMINANCE &&
661               type == GL_UNSIGNED_BYTE) {
662         memCopy = GL_TRUE;
663      }
664      else if (texImage->TexFormat == MESA_FORMAT_A8 &&
665               format == GL_ALPHA &&
666               type == GL_UNSIGNED_BYTE) {
667         memCopy = GL_TRUE;
668      }
669   }
670
671   if (memCopy) {
672      struct gl_pixelstore_attrib *pack = &ctx->Pack;
673
674      if (_mesa_is_bufferobj(pack->BufferObj)) {
675         /* Packing texture image into a PBO */
676         GLubyte *buf = (GLubyte *)
677            ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
678                                  GL_WRITE_ONLY_ARB, pack->BufferObj);
679         if (!buf) {
680            /* out of memory or other unexpected error */
681            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
682            return GL_TRUE; /* failed, but done */
683         }
684         pixels = ADD_POINTERS(buf, pixels);
685      }
686
687      {
688         const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
689         const GLuint bytesPerRow = texImage->Width * bpp;
690         GLubyte *dst =
691            _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
692                                  texImage->Height, format, type, 0, 0);
693         const GLint dstRowStride =
694            _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
695         const GLubyte *src = texImage->Data;
696         const GLint srcRowStride = texImage->RowStride * bpp;
697         GLuint row;
698
699         printf("Fast getteximage!\n");
700         for (row = 0; row < texImage->Height; row++) {
701            memcpy(dst, src, bytesPerRow);
702            dst += dstRowStride;
703            src += srcRowStride;
704         }
705      }
706
707      if (_mesa_is_bufferobj(pack->BufferObj)) {
708         ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
709      }
710   }
711
712   return memCopy;
713}
714
715
716/**
717 * Need to map texture image into memory before copying image data,
718 * then unmap it.
719 */
720static void
721intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
722		    GLenum format, GLenum type, GLvoid * pixels,
723		    struct gl_texture_object *texObj,
724		    struct gl_texture_image *texImage, GLboolean compressed)
725{
726   struct intel_context *intel = intel_context(ctx);
727   struct intel_texture_image *intelImage = intel_texture_image(texImage);
728
729   /* If we're reading from a texture that has been rendered to, need to
730    * make sure rendering is complete.
731    * We could probably predicate this on texObj->_RenderToTexture
732    */
733   intelFlush(ctx);
734
735   /* Map */
736   if (intelImage->mt) {
737      /* Image is stored in hardware format in a buffer managed by the
738       * kernel.  Need to explicitly map and unmap it.
739       */
740      intelImage->base.Data =
741         intel_miptree_image_map(intel,
742                                 intelImage->mt,
743                                 intelImage->face,
744                                 intelImage->level,
745                                 &intelImage->base.RowStride,
746                                 intelImage->base.ImageOffsets);
747      intelImage->base.RowStride /= intelImage->mt->cpp;
748   }
749   else {
750      /* Otherwise, the image should actually be stored in
751       * intelImage->base.Data.  This is pretty confusing for
752       * everybody, I'd much prefer to separate the two functions of
753       * texImage->Data - storage for texture images in main memory
754       * and access (ie mappings) of images.  In other words, we'd
755       * create a new texImage->Map field and leave Data simply for
756       * storage.
757       */
758      assert(intelImage->base.Data);
759   }
760
761
762   if (compressed) {
763      _mesa_get_compressed_teximage(ctx, target, level, pixels,
764				    texObj, texImage);
765   }
766   else {
767      if (!memcpy_get_tex_image(ctx, target, level, format, type, pixels,
768                                texObj, texImage)) {
769         _mesa_get_teximage(ctx, target, level, format, type, pixels,
770                            texObj, texImage);
771      }
772   }
773
774
775   /* Unmap */
776   if (intelImage->mt) {
777      intel_miptree_image_unmap(intel, intelImage->mt);
778      intelImage->base.Data = NULL;
779   }
780}
781
782
783static void
784intelGetTexImage(GLcontext * ctx, GLenum target, GLint level,
785                 GLenum format, GLenum type, GLvoid * pixels,
786                 struct gl_texture_object *texObj,
787                 struct gl_texture_image *texImage)
788{
789   intel_get_tex_image(ctx, target, level, format, type, pixels,
790		       texObj, texImage, GL_FALSE);
791}
792
793
794static void
795intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
796			   GLvoid *pixels,
797			   struct gl_texture_object *texObj,
798			   struct gl_texture_image *texImage)
799{
800   intel_get_tex_image(ctx, target, level, 0, 0, pixels,
801		       texObj, texImage, GL_TRUE);
802}
803
804
805void
806intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
807		  unsigned long long offset, GLint depth, GLuint pitch)
808{
809   struct intel_context *intel = pDRICtx->driverPrivate;
810   struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname);
811   struct intel_texture_object *intelObj = intel_texture_object(tObj);
812
813   if (!intelObj)
814      return;
815
816   if (intelObj->mt)
817      intel_miptree_release(intel, &intelObj->mt);
818
819   intelObj->imageOverride = GL_TRUE;
820   intelObj->depthOverride = depth;
821   intelObj->pitchOverride = pitch;
822
823   if (offset)
824      intelObj->textureOffset = offset;
825}
826
827void
828intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
829		   GLint glx_texture_format,
830		   __DRIdrawable *dPriv)
831{
832   struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
833   struct intel_context *intel = pDRICtx->driverPrivate;
834   struct intel_texture_object *intelObj;
835   struct intel_texture_image *intelImage;
836   struct intel_mipmap_tree *mt;
837   struct intel_renderbuffer *rb;
838   struct gl_texture_unit *texUnit;
839   struct gl_texture_object *texObj;
840   struct gl_texture_image *texImage;
841   int level = 0, type, format, internalFormat;
842
843   texUnit = &intel->ctx.Texture.Unit[intel->ctx.Texture.CurrentUnit];
844   texObj = _mesa_select_tex_object(&intel->ctx, texUnit, target);
845   intelObj = intel_texture_object(texObj);
846
847   if (!intelObj)
848      return;
849
850   intel_update_renderbuffers(pDRICtx, dPriv);
851
852   rb = intel_fb->color_rb[0];
853   /* If the region isn't set, then intel_update_renderbuffers was unable
854    * to get the buffers for the drawable.
855    */
856   if (rb->region == NULL)
857      return;
858
859   type = GL_BGRA;
860   format = GL_UNSIGNED_BYTE;
861   if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
862      internalFormat = GL_RGB;
863   else
864      internalFormat = GL_RGBA;
865
866   mt = intel_miptree_create_for_region(intel, target,
867					internalFormat,
868					0, 0, rb->region, 1, 0);
869   if (mt == NULL)
870       return;
871
872   _mesa_lock_texture(&intel->ctx, texObj);
873
874   texImage = _mesa_get_tex_image(&intel->ctx, texObj, target, level);
875   intelImage = intel_texture_image(texImage);
876
877   if (intelImage->mt) {
878      intel_miptree_release(intel, &intelImage->mt);
879      assert(!texImage->Data);
880   }
881   if (intelObj->mt)
882      intel_miptree_release(intel, &intelObj->mt);
883
884   intelObj->mt = mt;
885   _mesa_init_teximage_fields(&intel->ctx, target, texImage,
886			      rb->region->width, rb->region->height, 1,
887			      0, internalFormat);
888
889   intelImage->face = target_to_face(target);
890   intelImage->level = level;
891   texImage->RowStride = rb->region->pitch;
892   intel_miptree_reference(&intelImage->mt, intelObj->mt);
893
894   if (!intel_miptree_match_image(intelObj->mt, &intelImage->base,
895				  intelImage->face, intelImage->level)) {
896	   fprintf(stderr, "miptree doesn't match image\n");
897   }
898
899   _mesa_unlock_texture(&intel->ctx, texObj);
900}
901
902void
903intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
904{
905   /* The old interface didn't have the format argument, so copy our
906    * implementation's behavior at the time.
907    */
908   intelSetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
909}
910
911
912void
913intelInitTextureImageFuncs(struct dd_function_table *functions)
914{
915   functions->TexImage1D = intelTexImage1D;
916   functions->TexImage2D = intelTexImage2D;
917   functions->TexImage3D = intelTexImage3D;
918   functions->GetTexImage = intelGetTexImage;
919
920   functions->CompressedTexImage2D = intelCompressedTexImage2D;
921   functions->GetCompressedTexImage = intelGetCompressedTexImage;
922}
923