i915: Initialize swrast_texture_image structure fields.
[mesa.git] / src / mesa / swrast / s_texture.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2011 VMware, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * Functions for mapping/unmapping texture images.
26 */
27
28
29 #include "main/context.h"
30 #include "main/fbobject.h"
31 #include "main/teximage.h"
32 #include "swrast/swrast.h"
33 #include "swrast/s_context.h"
34
35
36 /**
37 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
38 * Called via ctx->Driver.NewTextureImage().
39 */
40 struct gl_texture_image *
41 _swrast_new_texture_image( struct gl_context *ctx )
42 {
43 (void) ctx;
44 return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
45 }
46
47
48 /**
49 * Free a swrast_texture_image (a subclass of gl_texture_image).
50 * Called via ctx->Driver.DeleteTextureImage().
51 */
52 void
53 _swrast_delete_texture_image(struct gl_context *ctx,
54 struct gl_texture_image *texImage)
55 {
56 /* Nothing special for the subclass yet */
57 _mesa_delete_texture_image(ctx, texImage);
58 }
59
60
61 /**
62 * Called via ctx->Driver.AllocTextureImageBuffer()
63 */
64 GLboolean
65 _swrast_alloc_texture_image_buffer(struct gl_context *ctx,
66 struct gl_texture_image *texImage,
67 gl_format format, GLsizei width,
68 GLsizei height, GLsizei depth)
69 {
70 struct swrast_texture_image *swImg = swrast_texture_image(texImage);
71 GLuint bytes = _mesa_format_image_size(format, width, height, depth);
72 GLuint i;
73
74 /* This _should_ be true (revisit if these ever fail) */
75 assert(texImage->Width == width);
76 assert(texImage->Height == height);
77 assert(texImage->Depth == depth);
78
79 assert(!swImg->Buffer);
80 swImg->Buffer = _mesa_align_malloc(bytes, 512);
81 if (!swImg->Buffer)
82 return GL_FALSE;
83
84 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
85 swImg->RowStride = width;
86
87 /* Allocate the ImageOffsets array and initialize to typical values.
88 * We allocate the array for 1D/2D textures too in order to avoid special-
89 * case code in the texstore routines.
90 */
91 swImg->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint));
92 if (!swImg->ImageOffsets)
93 return GL_FALSE;
94
95 for (i = 0; i < depth; i++) {
96 swImg->ImageOffsets[i] = i * width * height;
97 }
98
99 _swrast_init_texture_image(texImage, width, height, depth);
100
101 return GL_TRUE;
102 }
103
104
105 /**
106 * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
107 * initialize the fields of swrast_texture_image without allocating the image
108 * buffer or initializing ImageOffsets or RowStride.
109 *
110 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
111 */
112 void
113 _swrast_init_texture_image(struct gl_texture_image *texImage, GLsizei width,
114 GLsizei height, GLsizei depth)
115 {
116 struct swrast_texture_image *swImg = swrast_texture_image(texImage);
117
118 if ((width == 1 || _mesa_is_pow_two(texImage->Width2)) &&
119 (height == 1 || _mesa_is_pow_two(texImage->Height2)) &&
120 (depth == 1 || _mesa_is_pow_two(texImage->Depth2)))
121 swImg->_IsPowerOfTwo = GL_TRUE;
122 else
123 swImg->_IsPowerOfTwo = GL_FALSE;
124
125 /* Compute Width/Height/DepthScale for mipmap lod computation */
126 if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
127 /* scale = 1.0 since texture coords directly map to texels */
128 swImg->WidthScale = 1.0;
129 swImg->HeightScale = 1.0;
130 swImg->DepthScale = 1.0;
131 }
132 else {
133 swImg->WidthScale = (GLfloat) texImage->Width;
134 swImg->HeightScale = (GLfloat) texImage->Height;
135 swImg->DepthScale = (GLfloat) texImage->Depth;
136 }
137 }
138
139
140 /**
141 * Called via ctx->Driver.FreeTextureImageBuffer()
142 */
143 void
144 _swrast_free_texture_image_buffer(struct gl_context *ctx,
145 struct gl_texture_image *texImage)
146 {
147 struct swrast_texture_image *swImage = swrast_texture_image(texImage);
148 if (swImage->Buffer) {
149 _mesa_align_free(swImage->Buffer);
150 swImage->Buffer = NULL;
151 }
152
153 if (swImage->ImageOffsets) {
154 free(swImage->ImageOffsets);
155 swImage->ImageOffsets = NULL;
156 }
157 }
158
159
160 /**
161 * Error checking for debugging only.
162 */
163 static void
164 _mesa_check_map_teximage(struct gl_texture_image *texImage,
165 GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
166 {
167
168 if (texImage->TexObject->Target == GL_TEXTURE_1D)
169 assert(y == 0 && h == 1);
170
171 assert(x < texImage->Width || texImage->Width == 0);
172 assert(y < texImage->Height || texImage->Height == 0);
173 assert(x + w <= texImage->Width);
174 assert(y + h <= texImage->Height);
175 }
176
177 /**
178 * Map a 2D slice of a texture image into user space.
179 * (x,y,w,h) defines a region of interest (ROI). Reading/writing texels
180 * outside of the ROI is undefined.
181 *
182 * \param texImage the texture image
183 * \param slice the 3D image slice or array texture slice
184 * \param x, y, w, h region of interest
185 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
186 * \param mapOut returns start of mapping of region of interest
187 * \param rowStrideOut returns row stride (in bytes)
188 */
189 void
190 _swrast_map_teximage(struct gl_context *ctx,
191 struct gl_texture_image *texImage,
192 GLuint slice,
193 GLuint x, GLuint y, GLuint w, GLuint h,
194 GLbitfield mode,
195 GLubyte **mapOut,
196 GLint *rowStrideOut)
197 {
198 struct swrast_texture_image *swImage = swrast_texture_image(texImage);
199 GLubyte *map;
200 GLint stride, texelSize;
201 GLuint bw, bh;
202
203 _mesa_check_map_teximage(texImage, slice, x, y, w, h);
204
205 texelSize = _mesa_get_format_bytes(texImage->TexFormat);
206 stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
207 _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
208
209 assert(x % bw == 0);
210 assert(y % bh == 0);
211
212 if (!swImage->Buffer) {
213 /* probably ran out of memory when allocating tex mem */
214 *mapOut = NULL;
215 return;
216 }
217
218 map = swImage->Buffer;
219
220 if (texImage->TexObject->Target == GL_TEXTURE_3D ||
221 texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) {
222 GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
223 texImage->Width,
224 texImage->Height,
225 1);
226 assert(slice < texImage->Depth);
227 map += slice * sliceSize;
228 } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
229 GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
230 texImage->Width,
231 1,
232 1);
233 assert(slice < texImage->Height);
234 map += slice * sliceSize;
235 }
236
237 /* apply x/y offset to map address */
238 map += stride * (y / bh) + texelSize * (x / bw);
239
240 *mapOut = map;
241 *rowStrideOut = stride;
242 }
243
244 void
245 _swrast_unmap_teximage(struct gl_context *ctx,
246 struct gl_texture_image *texImage,
247 GLuint slice)
248 {
249 /* nop */
250 }
251
252
253 void
254 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
255 {
256 const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
257 GLuint face, level;
258
259 for (face = 0; face < faces; face++) {
260 for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
261 struct gl_texture_image *texImage = texObj->Image[face][level];
262 if (texImage) {
263 struct swrast_texture_image *swImage =
264 swrast_texture_image(texImage);
265
266 /* XXX we'll eventually call _swrast_map_teximage() here */
267 swImage->Map = swImage->Buffer;
268 }
269 }
270 }
271 }
272
273
274 void
275 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
276 {
277 const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
278 GLuint face, level;
279
280 for (face = 0; face < faces; face++) {
281 for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
282 struct gl_texture_image *texImage = texObj->Image[face][level];
283 if (texImage) {
284 struct swrast_texture_image *swImage
285 = swrast_texture_image(texImage);
286
287 /* XXX we'll eventually call _swrast_unmap_teximage() here */
288 swImage->Map = NULL;
289 }
290 }
291 }
292 }
293
294
295 /**
296 * Map all textures for reading prior to software rendering.
297 */
298 void
299 _swrast_map_textures(struct gl_context *ctx)
300 {
301 GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
302
303 /* loop over enabled texture units */
304 while (enabledUnits) {
305 GLuint unit = ffs(enabledUnits) - 1;
306 struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
307
308 _swrast_map_texture(ctx, texObj);
309
310 enabledUnits &= ~(1 << unit);
311 }
312 }
313
314
315 /**
316 * Unmap all textures for reading prior to software rendering.
317 */
318 void
319 _swrast_unmap_textures(struct gl_context *ctx)
320 {
321 GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
322
323 /* loop over enabled texture units */
324 while (enabledUnits) {
325 GLuint unit = ffs(enabledUnits) - 1;
326 struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
327
328 _swrast_unmap_texture(ctx, texObj);
329
330 enabledUnits &= ~(1 << unit);
331 }
332 }
333
334
335 /**
336 * Called via ctx->Driver.AllocTextureStorage()
337 * Just have to allocate memory for the texture images.
338 */
339 GLboolean
340 _swrast_AllocTextureStorage(struct gl_context *ctx,
341 struct gl_texture_object *texObj,
342 GLsizei levels, GLsizei width,
343 GLsizei height, GLsizei depth)
344 {
345 const GLint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
346 GLint face, level;
347
348 for (face = 0; face < numFaces; face++) {
349 for (level = 0; level < levels; level++) {
350 struct gl_texture_image *texImage = texObj->Image[face][level];
351 if (!_swrast_alloc_texture_image_buffer(ctx, texImage,
352 texImage->TexFormat,
353 texImage->Width,
354 texImage->Height,
355 texImage->Depth)) {
356 return GL_FALSE;
357 }
358 }
359 }
360
361 return GL_TRUE;
362 }
363