Home | History | Annotate | Download | only in swrast
      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 "main/texobj.h"
     33 #include "swrast/swrast.h"
     34 #include "swrast/s_context.h"
     35 
     36 
     37 /**
     38  * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
     39  * Called via ctx->Driver.NewTextureImage().
     40  */
     41 struct gl_texture_image *
     42 _swrast_new_texture_image( struct gl_context *ctx )
     43 {
     44    (void) ctx;
     45    return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
     46 }
     47 
     48 
     49 /**
     50  * Free a swrast_texture_image (a subclass of gl_texture_image).
     51  * Called via ctx->Driver.DeleteTextureImage().
     52  */
     53 void
     54 _swrast_delete_texture_image(struct gl_context *ctx,
     55                              struct gl_texture_image *texImage)
     56 {
     57    /* Nothing special for the subclass yet */
     58    _mesa_delete_texture_image(ctx, texImage);
     59 }
     60 
     61 
     62 /**
     63  * Called via ctx->Driver.AllocTextureImageBuffer()
     64  */
     65 GLboolean
     66 _swrast_alloc_texture_image_buffer(struct gl_context *ctx,
     67                                    struct gl_texture_image *texImage)
     68 {
     69    struct swrast_texture_image *swImg = swrast_texture_image(texImage);
     70    GLuint bytes = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
     71                                           texImage->Height, texImage->Depth);
     72    GLuint i;
     73 
     74    assert(!swImg->Buffer);
     75    swImg->Buffer = _mesa_align_malloc(bytes, 512);
     76    if (!swImg->Buffer)
     77       return GL_FALSE;
     78 
     79    /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
     80    swImg->RowStride = texImage->Width;
     81 
     82    /* Allocate the ImageOffsets array and initialize to typical values.
     83     * We allocate the array for 1D/2D textures too in order to avoid special-
     84     * case code in the texstore routines.
     85     */
     86    swImg->ImageOffsets = (GLuint *) malloc(texImage->Depth * sizeof(GLuint));
     87    if (!swImg->ImageOffsets)
     88       return GL_FALSE;
     89 
     90    for (i = 0; i < texImage->Depth; i++) {
     91       swImg->ImageOffsets[i] = i * texImage->Width * texImage->Height;
     92    }
     93 
     94    _swrast_init_texture_image(texImage);
     95 
     96    return GL_TRUE;
     97 }
     98 
     99 
    100 /**
    101  * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
    102  * initialize the fields of swrast_texture_image without allocating the image
    103  * buffer or initializing ImageOffsets or RowStride.
    104  *
    105  * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
    106  */
    107 void
    108 _swrast_init_texture_image(struct gl_texture_image *texImage)
    109 {
    110    struct swrast_texture_image *swImg = swrast_texture_image(texImage);
    111 
    112    if ((texImage->Width == 1 || _mesa_is_pow_two(texImage->Width2)) &&
    113        (texImage->Height == 1 || _mesa_is_pow_two(texImage->Height2)) &&
    114        (texImage->Depth == 1 || _mesa_is_pow_two(texImage->Depth2)))
    115       swImg->_IsPowerOfTwo = GL_TRUE;
    116    else
    117       swImg->_IsPowerOfTwo = GL_FALSE;
    118 
    119    /* Compute Width/Height/DepthScale for mipmap lod computation */
    120    if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
    121       /* scale = 1.0 since texture coords directly map to texels */
    122       swImg->WidthScale = 1.0;
    123       swImg->HeightScale = 1.0;
    124       swImg->DepthScale = 1.0;
    125    }
    126    else {
    127       swImg->WidthScale = (GLfloat) texImage->Width;
    128       swImg->HeightScale = (GLfloat) texImage->Height;
    129       swImg->DepthScale = (GLfloat) texImage->Depth;
    130    }
    131 }
    132 
    133 
    134 /**
    135  * Called via ctx->Driver.FreeTextureImageBuffer()
    136  */
    137 void
    138 _swrast_free_texture_image_buffer(struct gl_context *ctx,
    139                                   struct gl_texture_image *texImage)
    140 {
    141    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
    142    if (swImage->Buffer) {
    143       _mesa_align_free(swImage->Buffer);
    144       swImage->Buffer = NULL;
    145    }
    146 
    147    if (swImage->ImageOffsets) {
    148       free(swImage->ImageOffsets);
    149       swImage->ImageOffsets = NULL;
    150    }
    151 }
    152 
    153 
    154 /**
    155  * Error checking for debugging only.
    156  */
    157 static void
    158 _mesa_check_map_teximage(struct gl_texture_image *texImage,
    159                          GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
    160 {
    161 
    162    if (texImage->TexObject->Target == GL_TEXTURE_1D)
    163       assert(y == 0 && h == 1);
    164 
    165    assert(x < texImage->Width || texImage->Width == 0);
    166    assert(y < texImage->Height || texImage->Height == 0);
    167    assert(x + w <= texImage->Width);
    168    assert(y + h <= texImage->Height);
    169 }
    170 
    171 /**
    172  * Map a 2D slice of a texture image into user space.
    173  * (x,y,w,h) defines a region of interest (ROI).  Reading/writing texels
    174  * outside of the ROI is undefined.
    175  *
    176  * \param texImage  the texture image
    177  * \param slice  the 3D image slice or array texture slice
    178  * \param x, y, w, h  region of interest
    179  * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
    180  * \param mapOut  returns start of mapping of region of interest
    181  * \param rowStrideOut  returns row stride (in bytes)
    182  */
    183 void
    184 _swrast_map_teximage(struct gl_context *ctx,
    185                      struct gl_texture_image *texImage,
    186                      GLuint slice,
    187                      GLuint x, GLuint y, GLuint w, GLuint h,
    188                      GLbitfield mode,
    189                      GLubyte **mapOut,
    190                      GLint *rowStrideOut)
    191 {
    192    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
    193    GLubyte *map;
    194    GLint stride, texelSize;
    195    GLuint bw, bh;
    196 
    197    _mesa_check_map_teximage(texImage, slice, x, y, w, h);
    198 
    199    texelSize = _mesa_get_format_bytes(texImage->TexFormat);
    200    stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
    201    _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
    202 
    203    assert(x % bw == 0);
    204    assert(y % bh == 0);
    205 
    206    if (!swImage->Buffer) {
    207       /* probably ran out of memory when allocating tex mem */
    208       *mapOut = NULL;
    209       return;
    210    }
    211 
    212    map = swImage->Buffer;
    213 
    214    if (texImage->TexObject->Target == GL_TEXTURE_3D ||
    215        texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) {
    216       GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
    217                                                  texImage->Width,
    218                                                  texImage->Height,
    219                                                  1);
    220       assert(slice < texImage->Depth);
    221       map += slice * sliceSize;
    222    } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
    223       GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
    224                                                  texImage->Width,
    225                                                  1,
    226                                                  1);
    227       assert(slice < texImage->Height);
    228       map += slice * sliceSize;
    229    }
    230 
    231    /* apply x/y offset to map address */
    232    map += stride * (y / bh) + texelSize * (x / bw);
    233 
    234    *mapOut = map;
    235    *rowStrideOut = stride;
    236 }
    237 
    238 void
    239 _swrast_unmap_teximage(struct gl_context *ctx,
    240                        struct gl_texture_image *texImage,
    241                        GLuint slice)
    242 {
    243    /* nop */
    244 }
    245 
    246 
    247 void
    248 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
    249 {
    250    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
    251    GLuint face, level;
    252 
    253    for (face = 0; face < faces; face++) {
    254       for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
    255          struct gl_texture_image *texImage = texObj->Image[face][level];
    256          if (texImage) {
    257             struct swrast_texture_image *swImage =
    258                swrast_texture_image(texImage);
    259 
    260             /* XXX we'll eventually call _swrast_map_teximage() here */
    261             swImage->Map = swImage->Buffer;
    262          }
    263       }
    264    }
    265 }
    266 
    267 
    268 void
    269 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
    270 {
    271    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
    272    GLuint face, level;
    273 
    274    for (face = 0; face < faces; face++) {
    275       for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
    276          struct gl_texture_image *texImage = texObj->Image[face][level];
    277          if (texImage) {
    278             struct swrast_texture_image *swImage
    279                = swrast_texture_image(texImage);
    280 
    281             /* XXX we'll eventually call _swrast_unmap_teximage() here */
    282             swImage->Map = NULL;
    283          }
    284       }
    285    }
    286 }
    287 
    288 
    289 /**
    290  * Map all textures for reading prior to software rendering.
    291  */
    292 void
    293 _swrast_map_textures(struct gl_context *ctx)
    294 {
    295    GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
    296 
    297    /* loop over enabled texture units */
    298    while (enabledUnits) {
    299       GLuint unit = ffs(enabledUnits) - 1;
    300       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
    301 
    302       _swrast_map_texture(ctx, texObj);
    303 
    304       enabledUnits &= ~(1 << unit);
    305    }
    306 }
    307 
    308 
    309 /**
    310  * Unmap all textures for reading prior to software rendering.
    311  */
    312 void
    313 _swrast_unmap_textures(struct gl_context *ctx)
    314 {
    315    GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
    316 
    317    /* loop over enabled texture units */
    318    while (enabledUnits) {
    319       GLuint unit = ffs(enabledUnits) - 1;
    320       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
    321 
    322       _swrast_unmap_texture(ctx, texObj);
    323 
    324       enabledUnits &= ~(1 << unit);
    325    }
    326 }
    327 
    328 
    329 /**
    330  * Called via ctx->Driver.AllocTextureStorage()
    331  * Just have to allocate memory for the texture images.
    332  */
    333 GLboolean
    334 _swrast_AllocTextureStorage(struct gl_context *ctx,
    335                             struct gl_texture_object *texObj,
    336                             GLsizei levels, GLsizei width,
    337                             GLsizei height, GLsizei depth)
    338 {
    339    const GLint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
    340    GLint face, level;
    341 
    342    for (face = 0; face < numFaces; face++) {
    343       for (level = 0; level < levels; level++) {
    344          struct gl_texture_image *texImage = texObj->Image[face][level];
    345          if (!_swrast_alloc_texture_image_buffer(ctx, texImage)) {
    346             return GL_FALSE;
    347          }
    348       }
    349    }
    350 
    351    return GL_TRUE;
    352 }
    353 
    354