mesa: remove _mesa_alloc_texmemory(), _mesa_free_texmemory()
[mesa.git] / src / mesa / drivers / dri / intel / intel_tex.c
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
13 static struct gl_texture_image *
14 intelNewTextureImage(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
21 static void
22 intelDeleteTextureImage(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
29 static struct gl_texture_object *
30 intelNewTextureObject(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
42 static void
43 intelDeleteTextureObject(struct gl_context *ctx,
44 struct gl_texture_object *texObj)
45 {
46 struct intel_texture_object *intelObj = intel_texture_object(texObj);
47
48 intel_miptree_release(&intelObj->mt);
49 _mesa_delete_texture_object(ctx, texObj);
50 }
51
52 static GLboolean
53 intel_alloc_texture_image_buffer(struct gl_context *ctx,
54 struct gl_texture_image *image,
55 gl_format format, GLsizei width,
56 GLsizei height, GLsizei depth)
57 {
58 struct intel_context *intel = intel_context(ctx);
59 struct intel_texture_image *intel_image = intel_texture_image(image);
60 struct gl_texture_object *texobj = image->TexObject;
61 struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
62 GLuint slices;
63
64 /* Because the driver uses AllocTextureImageBuffer() internally, it may end
65 * up mismatched with FreeTextureImageBuffer(), but that is safe to call
66 * multiple times.
67 */
68 ctx->Driver.FreeTextureImageBuffer(ctx, image);
69
70 if (intel->must_use_separate_stencil
71 && image->TexFormat == MESA_FORMAT_S8_Z24) {
72 intel_tex_image_s8z24_create_renderbuffers(intel, intel_image);
73 }
74
75 /* Allocate the swrast_texture_image::ImageOffsets array now */
76 switch (texobj->Target) {
77 case GL_TEXTURE_3D:
78 case GL_TEXTURE_2D_ARRAY:
79 slices = image->Depth;
80 break;
81 case GL_TEXTURE_1D_ARRAY:
82 slices = image->Height;
83 break;
84 default:
85 slices = 1;
86 }
87 assert(!intel_image->base.ImageOffsets);
88 intel_image->base.ImageOffsets = malloc(slices * sizeof(GLuint));
89
90 if (intel_texobj->mt &&
91 intel_miptree_match_image(intel_texobj->mt, image)) {
92 intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
93 DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n",
94 __FUNCTION__, texobj, image->Level,
95 width, height, depth, intel_texobj->mt);
96 return true;
97 } else if (image->Border == 0) {
98 intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj,
99 intel_image,
100 false);
101
102 /* Even if the object currently has a mipmap tree associated
103 * with it, this one is a more likely candidate to represent the
104 * whole object since our level didn't fit what was there
105 * before, and any lower levels would fit into our miptree.
106 */
107 intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
108
109 if (intel->must_use_separate_stencil
110 && image->TexFormat == MESA_FORMAT_S8_Z24) {
111 intel_tex_image_s8z24_create_renderbuffers(intel, intel_image);
112 }
113
114 DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
115 __FUNCTION__, texobj, image->Level,
116 width, height, depth, intel_image->mt);
117 return true;
118 }
119
120 DBG("%s: alloc obj %p level %d %dx%dx%d using swrast\n",
121 __FUNCTION__, texobj, image->Level, width, height, depth);
122
123 return _swrast_alloc_texture_image_buffer(ctx, image, format,
124 width, height, depth);
125 }
126
127 static void
128 intel_free_texture_image_buffer(struct gl_context * ctx,
129 struct gl_texture_image *texImage)
130 {
131 struct intel_texture_image *intelImage = intel_texture_image(texImage);
132
133 DBG("%s\n", __FUNCTION__);
134
135 intel_miptree_release(&intelImage->mt);
136
137 if (intelImage->base.Data) {
138 _mesa_align_free(intelImage->base.Data);
139 intelImage->base.Data = NULL;
140 }
141
142 if (intelImage->base.ImageOffsets) {
143 free(intelImage->base.ImageOffsets);
144 intelImage->base.ImageOffsets = NULL;
145 }
146
147 _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
148 _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
149 }
150
151 /**
152 * Map texture memory/buffer into user space.
153 * Note: the region of interest parameters are ignored here.
154 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
155 * \param mapOut returns start of mapping of region of interest
156 * \param rowStrideOut returns row stride in bytes
157 */
158 static void
159 intel_map_texture_image(struct gl_context *ctx,
160 struct gl_texture_image *tex_image,
161 GLuint slice,
162 GLuint x, GLuint y, GLuint w, GLuint h,
163 GLbitfield mode,
164 GLubyte **map,
165 GLint *stride)
166 {
167 struct intel_context *intel = intel_context(ctx);
168 struct intel_texture_image *intel_image = intel_texture_image(tex_image);
169 struct intel_mipmap_tree *mt = intel_image->mt;
170 unsigned int bw, bh;
171
172 /* Check that our caller wasn't confused about how to map a 1D texture. */
173 assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
174 h == 1);
175
176 if (intel_image->stencil_rb) {
177 /*
178 * The texture has packed depth/stencil format, but uses separate
179 * stencil. The texture's embedded stencil buffer contains the real
180 * stencil data, so copy that into the miptree.
181 */
182 intel_tex_image_s8z24_gather(intel, intel_image);
183 }
184
185 /* For compressed formats, the stride is the number of bytes per
186 * row of blocks. intel_miptree_get_image_offset() already does
187 * the divide.
188 */
189 _mesa_get_format_block_size(tex_image->TexFormat, &bw, &bh);
190 assert(y % bh == 0);
191 y /= bh;
192
193 if (likely(mt)) {
194 void *base = intel_region_map(intel, mt->region, mode);
195 unsigned int image_x, image_y;
196
197 intel_miptree_get_image_offset(mt, tex_image->Level, tex_image->Face,
198 slice, &image_x, &image_y);
199 x += image_x;
200 y += image_y;
201
202 *stride = mt->region->pitch * mt->cpp;
203 *map = base + y * *stride + x * mt->cpp;
204
205 DBG("%s: %d,%d %dx%d from mt %p %d,%d = %p/%d\n", __FUNCTION__,
206 x - image_x, y - image_y, w, h,
207 mt, x, y, *map, *stride);
208 } else {
209 /* texture data is in malloc'd memory */
210 GLuint width = tex_image->Width;
211 GLuint height = ALIGN(tex_image->Height, bh) / bh;
212 GLuint texelSize = _mesa_get_format_bytes(tex_image->TexFormat);
213
214 assert(map);
215
216 *stride = _mesa_format_row_stride(tex_image->TexFormat, width);
217 *map = intel_image->base.Data + (slice * height + y) * *stride + x * texelSize;
218
219 DBG("%s: %d,%d %dx%d from data %p = %p/%d\n", __FUNCTION__,
220 x, y, w, h,
221 intel_image->base.Data, *map, *stride);
222 }
223 }
224
225 static void
226 intel_unmap_texture_image(struct gl_context *ctx,
227 struct gl_texture_image *tex_image, GLuint slice)
228 {
229 struct intel_context *intel = intel_context(ctx);
230 struct intel_texture_image *intel_image = intel_texture_image(tex_image);
231
232 if (intel_image->mt)
233 intel_region_unmap(intel, intel_image->mt->region);
234
235 if (intel_image->stencil_rb) {
236 /*
237 * The texture has packed depth/stencil format, but uses separate
238 * stencil. The texture's embedded stencil buffer contains the real
239 * stencil data, so copy that into the miptree.
240 */
241 intel_tex_image_s8z24_scatter(intel, intel_image);
242 }
243 }
244
245 /**
246 * Called via ctx->Driver.GenerateMipmap()
247 * This is basically a wrapper for _mesa_meta_GenerateMipmap() which checks
248 * if we'll be using software mipmap generation. In that case, we need to
249 * map/unmap the base level texture image.
250 */
251 static void
252 intelGenerateMipmap(struct gl_context *ctx, GLenum target,
253 struct gl_texture_object *texObj)
254 {
255 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
256 fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
257
258 _mesa_generate_mipmap(ctx, target, texObj);
259 }
260 else {
261 _mesa_meta_GenerateMipmap(ctx, target, texObj);
262 }
263 }
264
265
266 void
267 intelInitTextureFuncs(struct dd_function_table *functions)
268 {
269 functions->GenerateMipmap = intelGenerateMipmap;
270
271 functions->NewTextureObject = intelNewTextureObject;
272 functions->NewTextureImage = intelNewTextureImage;
273 functions->DeleteTextureImage = intelDeleteTextureImage;
274 functions->DeleteTexture = intelDeleteTextureObject;
275 functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer;
276 functions->FreeTextureImageBuffer = intel_free_texture_image_buffer;
277 functions->MapTextureImage = intel_map_texture_image;
278 functions->UnmapTextureImage = intel_unmap_texture_image;
279 }