intel_tex.c revision 455a19b1b3d7ca0a40c65d89e45209dbd8ac7b35
1#include "swrast/swrast.h"
2#include "main/renderbuffer.h"
3#include "main/texobj.h"
4#include "main/teximage.h"
5#include "main/mipmap.h"
6#include "drivers/common/meta.h"
7#include "intel_context.h"
8#include "intel_mipmap_tree.h"
9#include "intel_tex.h"
10
11#define FILE_DEBUG_FLAG DEBUG_TEXTURE
12
13static struct gl_texture_image *
14intelNewTextureImage(struct gl_context * ctx)
15{
16   DBG("%s\n", __FUNCTION__);
17   (void) ctx;
18   return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image);
19}
20
21static void
22intelDeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img)
23{
24   /* nothing special (yet) for intel_texture_image */
25   _mesa_delete_texture_image(ctx, img);
26}
27
28
29static struct gl_texture_object *
30intelNewTextureObject(struct gl_context * ctx, GLuint name, GLenum target)
31{
32   struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
33
34   (void) ctx;
35
36   DBG("%s\n", __FUNCTION__);
37   _mesa_initialize_texture_object(&obj->base, name, target);
38
39   return &obj->base;
40}
41
42static void
43intelDeleteTextureObject(struct gl_context *ctx,
44			 struct gl_texture_object *texObj)
45{
46   struct intel_context *intel = intel_context(ctx);
47   struct intel_texture_object *intelObj = intel_texture_object(texObj);
48
49   if (intelObj->mt)
50      intel_miptree_release(intel, &intelObj->mt);
51
52   _mesa_delete_texture_object(ctx, texObj);
53}
54
55
56static void
57intel_free_texture_image_buffer(struct gl_context * ctx,
58				struct gl_texture_image *texImage)
59{
60   struct intel_context *intel = intel_context(ctx);
61   struct intel_texture_image *intelImage = intel_texture_image(texImage);
62
63   DBG("%s\n", __FUNCTION__);
64
65   if (intelImage->mt) {
66      intel_miptree_release(intel, &intelImage->mt);
67   }
68
69   if (texImage->Data) {
70      _mesa_free_texmemory(texImage->Data);
71      texImage->Data = NULL;
72   }
73
74   if (intelImage->depth_rb) {
75      _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
76   }
77
78   if (intelImage->stencil_rb) {
79      _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
80   }
81}
82
83/**
84 * Map texture memory/buffer into user space.
85 * Note: the region of interest parameters are ignored here.
86 * \param mapOut  returns start of mapping of region of interest
87 * \param rowStrideOut  returns row stride in bytes
88 */
89static void
90intel_map_texture_image(struct gl_context *ctx,
91			struct gl_texture_image *tex_image,
92			GLuint slice,
93			GLuint x, GLuint y, GLuint w, GLuint h,
94			GLbitfield mode,
95			GLubyte **map,
96			GLint *stride)
97{
98   struct intel_context *intel = intel_context(ctx);
99   struct intel_texture_image *intel_image = intel_texture_image(tex_image);
100   struct intel_mipmap_tree *mt = intel_image->mt;
101   unsigned int bw, bh;
102
103   if (intel_image->stencil_rb) {
104      /*
105       * The texture has packed depth/stencil format, but uses separate
106       * stencil. The texture's embedded stencil buffer contains the real
107       * stencil data, so copy that into the miptree.
108       */
109      intel_tex_image_s8z24_gather(intel, intel_image);
110   }
111
112   /* For compressed formats, the stride is the number of bytes per
113    * row of blocks.  intel_miptree_get_image_offset() already does
114    * the divide.
115    */
116   _mesa_get_format_block_size(tex_image->TexFormat, &bw, &bh);
117   assert(y % bh == 0);
118   y /= bh;
119
120   if (likely(mt)) {
121      void *base = intel_region_map(intel, mt->region);
122      unsigned int image_x, image_y;
123
124      intel_miptree_get_image_offset(mt, tex_image->Level, tex_image->Face,
125				     slice, &image_x, &image_y);
126      x += image_x;
127      y += image_y;
128
129      *stride = mt->region->pitch * mt->cpp;
130      *map = base + y * *stride + x * mt->cpp;
131   } else {
132      /* texture data is in malloc'd memory */
133      GLuint width = tex_image->Width;
134      GLuint height = ALIGN(tex_image->Height, bh) / bh;
135      GLuint texelSize = _mesa_get_format_bytes(tex_image->TexFormat);
136
137      assert(map);
138
139      *stride = _mesa_format_row_stride(tex_image->TexFormat, width);
140      *map = tex_image->Data + (slice * height + y) * *stride + x * texelSize;
141
142      return;
143   }
144}
145
146static void
147intel_unmap_texture_image(struct gl_context *ctx,
148			  struct gl_texture_image *tex_image, GLuint slice)
149{
150   struct intel_context *intel = intel_context(ctx);
151   struct intel_texture_image *intel_image = intel_texture_image(tex_image);
152
153   if (intel_image->mt)
154      intel_region_unmap(intel, intel_image->mt->region);
155
156   if (intel_image->stencil_rb) {
157      /*
158       * The texture has packed depth/stencil format, but uses separate
159       * stencil. The texture's embedded stencil buffer contains the real
160       * stencil data, so copy that into the miptree.
161       */
162      intel_tex_image_s8z24_scatter(intel, intel_image);
163   }
164}
165
166/**
167 * Called via ctx->Driver.GenerateMipmap()
168 * This is basically a wrapper for _mesa_meta_GenerateMipmap() which checks
169 * if we'll be using software mipmap generation.  In that case, we need to
170 * map/unmap the base level texture image.
171 */
172static void
173intelGenerateMipmap(struct gl_context *ctx, GLenum target,
174                    struct gl_texture_object *texObj)
175{
176   if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
177      /* sw path: need to map texture images */
178      struct intel_context *intel = intel_context(ctx);
179      struct intel_texture_object *intelObj = intel_texture_object(texObj);
180      struct gl_texture_image *first_image = texObj->Image[0][texObj->BaseLevel];
181
182      fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
183
184      intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel);
185      _mesa_generate_mipmap(ctx, target, texObj);
186      intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel);
187
188      if (!_mesa_is_format_compressed(first_image->TexFormat)) {
189         GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
190         GLuint face, i;
191         for (face = 0; face < nr_faces; face++) {
192            for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
193               struct intel_texture_image *intelImage =
194                  intel_texture_image(texObj->Image[face][i]);
195               if (!intelImage)
196                  break;
197               /* Unreference the miptree to signal that the new Data is a
198                * bare pointer from mesa.
199                */
200               intel_miptree_release(intel, &intelImage->mt);
201            }
202         }
203      }
204   }
205   else {
206      _mesa_meta_GenerateMipmap(ctx, target, texObj);
207   }
208}
209
210
211void
212intelInitTextureFuncs(struct dd_function_table *functions)
213{
214   functions->GenerateMipmap = intelGenerateMipmap;
215
216   functions->NewTextureObject = intelNewTextureObject;
217   functions->NewTextureImage = intelNewTextureImage;
218   functions->DeleteTextureImage = intelDeleteTextureImage;
219   functions->DeleteTexture = intelDeleteTextureObject;
220   functions->FreeTextureImageBuffer = intel_free_texture_image_buffer;
221   functions->MapTextureImage = intel_map_texture_image;
222   functions->UnmapTextureImage = intel_unmap_texture_image;
223}
224