Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
/**
26
 * Functions for mapping/unmapping texture images.
27
 */
28
 
29
 
30
#include "main/context.h"
31
#include "main/fbobject.h"
32
#include "main/teximage.h"
33
#include "main/texobj.h"
34
#include "swrast/swrast.h"
35
#include "swrast/s_context.h"
36
 
37
 
38
/**
39
 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
40
 * Called via ctx->Driver.NewTextureImage().
41
 */
42
struct gl_texture_image *
43
_swrast_new_texture_image( struct gl_context *ctx )
44
{
45
   (void) ctx;
46
   return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
47
}
48
 
49
 
50
/**
51
 * Free a swrast_texture_image (a subclass of gl_texture_image).
52
 * Called via ctx->Driver.DeleteTextureImage().
53
 */
54
void
55
_swrast_delete_texture_image(struct gl_context *ctx,
56
                             struct gl_texture_image *texImage)
57
{
58
   /* Nothing special for the subclass yet */
59
   _mesa_delete_texture_image(ctx, texImage);
60
}
61
 
62
static unsigned int
63
texture_slices(struct gl_texture_image *texImage)
64
{
65
   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
66
      return texImage->Height;
67
   else
68
      return texImage->Depth;
69
}
70
 
71
unsigned int
72
_swrast_teximage_slice_height(struct gl_texture_image *texImage)
73
{
74
   /* For 1D array textures, the slices are all 1 pixel high, and Height is
75
    * the number of slices.
76
    */
77
   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
78
      return 1;
79
   else
80
      return texImage->Height;
81
}
82
 
83
/**
84
 * Called via ctx->Driver.AllocTextureImageBuffer()
85
 */
86
GLboolean
87
_swrast_alloc_texture_image_buffer(struct gl_context *ctx,
88
                                   struct gl_texture_image *texImage)
89
{
90
   struct swrast_texture_image *swImg = swrast_texture_image(texImage);
91
   GLuint bytesPerSlice;
92
   GLuint slices = texture_slices(texImage);
93
   GLuint i;
94
 
95
   if (!_swrast_init_texture_image(texImage))
96
      return GL_FALSE;
97
 
98
   bytesPerSlice = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
99
                                           _swrast_teximage_slice_height(texImage), 1);
100
 
101
   assert(!swImg->Buffer);
102
   swImg->Buffer = _mesa_align_malloc(bytesPerSlice * slices, 512);
103
   if (!swImg->Buffer)
104
      return GL_FALSE;
105
 
106
   /* RowStride and ImageSlices[] describe how to address texels in 'Data' */
107
   swImg->RowStride = _mesa_format_row_stride(texImage->TexFormat,
108
                                              texImage->Width);
109
 
110
   for (i = 0; i < slices; i++) {
111
      swImg->ImageSlices[i] = swImg->Buffer + bytesPerSlice * i;
112
   }
113
 
114
   return GL_TRUE;
115
}
116
 
117
 
118
/**
119
 * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
120
 * initialize the fields of swrast_texture_image without allocating the image
121
 * buffer or initializing RowStride or the contents of ImageSlices.
122
 *
123
 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
124
 */
125
GLboolean
126
_swrast_init_texture_image(struct gl_texture_image *texImage)
127
{
128
   struct swrast_texture_image *swImg = swrast_texture_image(texImage);
129
 
130
   if ((texImage->Width == 1 || _mesa_is_pow_two(texImage->Width2)) &&
131
       (texImage->Height == 1 || _mesa_is_pow_two(texImage->Height2)) &&
132
       (texImage->Depth == 1 || _mesa_is_pow_two(texImage->Depth2)))
133
      swImg->_IsPowerOfTwo = GL_TRUE;
134
   else
135
      swImg->_IsPowerOfTwo = GL_FALSE;
136
 
137
   /* Compute Width/Height/DepthScale for mipmap lod computation */
138
   if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
139
      /* scale = 1.0 since texture coords directly map to texels */
140
      swImg->WidthScale = 1.0;
141
      swImg->HeightScale = 1.0;
142
      swImg->DepthScale = 1.0;
143
   }
144
   else {
145
      swImg->WidthScale = (GLfloat) texImage->Width;
146
      swImg->HeightScale = (GLfloat) texImage->Height;
147
      swImg->DepthScale = (GLfloat) texImage->Depth;
148
   }
149
 
150
   assert(!swImg->ImageSlices);
151
   swImg->ImageSlices = calloc(texture_slices(texImage), sizeof(void *));
152
   if (!swImg->ImageSlices)
153
      return GL_FALSE;
154
 
155
   return GL_TRUE;
156
}
157
 
158
 
159
/**
160
 * Called via ctx->Driver.FreeTextureImageBuffer()
161
 */
162
void
163
_swrast_free_texture_image_buffer(struct gl_context *ctx,
164
                                  struct gl_texture_image *texImage)
165
{
166
   struct swrast_texture_image *swImage = swrast_texture_image(texImage);
167
   if (swImage->Buffer) {
168
      _mesa_align_free(swImage->Buffer);
169
      swImage->Buffer = NULL;
170
   }
171
 
172
   free(swImage->ImageSlices);
173
   swImage->ImageSlices = NULL;
174
}
175
 
176
 
177
/**
178
 * Error checking for debugging only.
179
 */
180
static void
181
_mesa_check_map_teximage(struct gl_texture_image *texImage,
182
                         GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
183
{
184
 
185
   if (texImage->TexObject->Target == GL_TEXTURE_1D)
186
      assert(y == 0 && h == 1);
187
 
188
   assert(x < texImage->Width || texImage->Width == 0);
189
   assert(y < texImage->Height || texImage->Height == 0);
190
   assert(x + w <= texImage->Width);
191
   assert(y + h <= texImage->Height);
192
}
193
 
194
/**
195
 * Map a 2D slice of a texture image into user space.
196
 * (x,y,w,h) defines a region of interest (ROI).  Reading/writing texels
197
 * outside of the ROI is undefined.
198
 *
199
 * \param texImage  the texture image
200
 * \param slice  the 3D image slice or array texture slice
201
 * \param x, y, w, h  region of interest
202
 * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
203
 * \param mapOut  returns start of mapping of region of interest
204
 * \param rowStrideOut  returns row stride (in bytes)
205
 */
206
void
207
_swrast_map_teximage(struct gl_context *ctx,
208
                     struct gl_texture_image *texImage,
209
                     GLuint slice,
210
                     GLuint x, GLuint y, GLuint w, GLuint h,
211
                     GLbitfield mode,
212
                     GLubyte **mapOut,
213
                     GLint *rowStrideOut)
214
{
215
   struct swrast_texture_image *swImage = swrast_texture_image(texImage);
216
   GLubyte *map;
217
   GLint stride, texelSize;
218
   GLuint bw, bh;
219
 
220
   _mesa_check_map_teximage(texImage, slice, x, y, w, h);
221
 
222
   texelSize = _mesa_get_format_bytes(texImage->TexFormat);
223
   stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
224
   _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
225
 
226
   assert(x % bw == 0);
227
   assert(y % bh == 0);
228
 
229
   if (!swImage->Buffer) {
230
      /* probably ran out of memory when allocating tex mem */
231
      *mapOut = NULL;
232
      return;
233
   }
234
 
235
   /* This function can only be used with a swrast-allocated buffer, in which
236
    * case ImageSlices is populated with pointers into Buffer.
237
    */
238
   assert(swImage->Buffer);
239
   assert(swImage->Buffer == swImage->ImageSlices[0]);
240
 
241
   assert(slice < texture_slices(texImage));
242
   map = swImage->ImageSlices[slice];
243
 
244
   /* apply x/y offset to map address */
245
   map += stride * (y / bh) + texelSize * (x / bw);
246
 
247
   *mapOut = map;
248
   *rowStrideOut = stride;
249
}
250
 
251
void
252
_swrast_unmap_teximage(struct gl_context *ctx,
253
                       struct gl_texture_image *texImage,
254
                       GLuint slice)
255
{
256
   /* nop */
257
}
258
 
259
 
260
void
261
_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
262
{
263
   const GLuint faces = _mesa_num_tex_faces(texObj->Target);
264
   GLuint face, level;
265
 
266
   for (face = 0; face < faces; face++) {
267
      for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
268
         struct gl_texture_image *texImage = texObj->Image[face][level];
269
         struct swrast_texture_image *swImage = swrast_texture_image(texImage);
270
         unsigned int i;
271
 
272
         if (!texImage)
273
            continue;
274
 
275
         /* In the case of a swrast-allocated texture buffer, the ImageSlices
276
          * and RowStride are always available.
277
          */
278
         if (swImage->Buffer) {
279
            assert(swImage->ImageSlices[0] == swImage->Buffer);
280
            continue;
281
         }
282
 
283
         for (i = 0; i < texture_slices(texImage); i++) {
284
            GLubyte *map;
285
            GLint rowStride;
286
 
287
            if (swImage->ImageSlices[i])
288
               continue;
289
 
290
            ctx->Driver.MapTextureImage(ctx, texImage, i,
291
                                        0, 0,
292
                                        texImage->Width, texImage->Height,
293
                                        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
294
                                        &map, &rowStride);
295
 
296
            swImage->ImageSlices[i] = map;
297
            /* A swrast-using driver has to return the same rowstride for
298
             * every slice of the same texture, since we don't track them
299
             * separately.
300
             */
301
            if (i == 0)
302
               swImage->RowStride = rowStride;
303
            else
304
               assert(swImage->RowStride == rowStride);
305
         }
306
      }
307
   }
308
}
309
 
310
 
311
void
312
_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
313
{
314
   const GLuint faces = _mesa_num_tex_faces(texObj->Target);
315
   GLuint face, level;
316
 
317
   for (face = 0; face < faces; face++) {
318
      for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
319
         struct gl_texture_image *texImage = texObj->Image[face][level];
320
         struct swrast_texture_image *swImage = swrast_texture_image(texImage);
321
         unsigned int i;
322
 
323
         if (!texImage)
324
            continue;
325
 
326
         if (swImage->Buffer)
327
            return;
328
 
329
         for (i = 0; i < texture_slices(texImage); i++) {
330
            if (swImage->ImageSlices[i]) {
331
               ctx->Driver.UnmapTextureImage(ctx, texImage, i);
332
               swImage->ImageSlices[i] = NULL;
333
            }
334
         }
335
      }
336
   }
337
}
338
 
339
 
340
/**
341
 * Map all textures for reading prior to software rendering.
342
 */
343
void
344
_swrast_map_textures(struct gl_context *ctx)
345
{
346
   GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
347
 
348
   /* loop over enabled texture units */
349
   while (enabledUnits) {
350
      GLuint unit = ffs(enabledUnits) - 1;
351
      struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
352
 
353
      _swrast_map_texture(ctx, texObj);
354
 
355
      enabledUnits &= ~(1 << unit);
356
   }
357
}
358
 
359
 
360
/**
361
 * Unmap all textures for reading prior to software rendering.
362
 */
363
void
364
_swrast_unmap_textures(struct gl_context *ctx)
365
{
366
   GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
367
 
368
   /* loop over enabled texture units */
369
   while (enabledUnits) {
370
      GLuint unit = ffs(enabledUnits) - 1;
371
      struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
372
 
373
      _swrast_unmap_texture(ctx, texObj);
374
 
375
      enabledUnits &= ~(1 << unit);
376
   }
377
}