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 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(const 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 
    168    _mesa_align_free(swImage->Buffer);
    169    swImage->Buffer = NULL;
    170 
    171    free(swImage->ImageSlices);
    172    swImage->ImageSlices = NULL;
    173 }
    174 
    175 
    176 /**
    177  * Error checking for debugging only.
    178  */
    179 static void
    180 check_map_teximage(const struct gl_texture_image *texImage,
    181                    GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
    182 {
    183 
    184    if (texImage->TexObject->Target == GL_TEXTURE_1D)
    185       assert(y == 0 && h == 1);
    186 
    187    assert(x < texImage->Width || texImage->Width == 0);
    188    assert(y < texImage->Height || texImage->Height == 0);
    189    assert(x + w <= texImage->Width);
    190    assert(y + h <= texImage->Height);
    191    assert(slice < texture_slices(texImage));
    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    check_map_teximage(texImage, slice, x, y, w, h);
    221 
    222    if (!swImage->Buffer) {
    223       /* Either glTexImage was called with a NULL <pixels> argument or
    224        * we ran out of memory when allocating texture memory,
    225        */
    226       *mapOut = NULL;
    227       *rowStrideOut = 0;
    228       return;
    229    }
    230 
    231    texelSize = _mesa_get_format_bytes(texImage->TexFormat);
    232    stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
    233    _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
    234 
    235    assert(x % bw == 0);
    236    assert(y % bh == 0);
    237 
    238    /* This function can only be used with a swrast-allocated buffer, in which
    239     * case ImageSlices is populated with pointers into Buffer.
    240     */
    241    assert(swImage->Buffer);
    242    assert(swImage->Buffer == swImage->ImageSlices[0]);
    243 
    244    map = swImage->ImageSlices[slice];
    245 
    246    /* apply x/y offset to map address */
    247    map += stride * (y / bh) + texelSize * (x / bw);
    248 
    249    *mapOut = map;
    250    *rowStrideOut = stride;
    251 }
    252 
    253 void
    254 _swrast_unmap_teximage(struct gl_context *ctx,
    255                        struct gl_texture_image *texImage,
    256                        GLuint slice)
    257 {
    258    /* nop */
    259 }
    260 
    261 
    262 void
    263 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
    264 {
    265    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
    266    GLuint face, level;
    267 
    268    for (face = 0; face < faces; face++) {
    269       for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
    270          struct gl_texture_image *texImage = texObj->Image[face][level];
    271          struct swrast_texture_image *swImage = swrast_texture_image(texImage);
    272          unsigned int i, slices;
    273 
    274          if (!texImage)
    275             continue;
    276 
    277          /* In the case of a swrast-allocated texture buffer, the ImageSlices
    278           * and RowStride are always available.
    279           */
    280          if (swImage->Buffer) {
    281             assert(swImage->ImageSlices[0] == swImage->Buffer);
    282             continue;
    283          }
    284 
    285          if (!swImage->ImageSlices) {
    286             swImage->ImageSlices =
    287                calloc(texture_slices(texImage), sizeof(void *));
    288             if (!swImage->ImageSlices)
    289                continue;
    290          }
    291 
    292          slices = texture_slices(texImage);
    293 
    294          for (i = 0; i < slices; i++) {
    295             GLubyte *map;
    296             GLint rowStride;
    297 
    298             if (swImage->ImageSlices[i])
    299                continue;
    300 
    301             ctx->Driver.MapTextureImage(ctx, texImage, i,
    302                                         0, 0,
    303                                         texImage->Width, texImage->Height,
    304                                         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
    305                                         &map, &rowStride);
    306 
    307             swImage->ImageSlices[i] = map;
    308             /* A swrast-using driver has to return the same rowstride for
    309              * every slice of the same texture, since we don't track them
    310              * separately.
    311              */
    312             if (i == 0)
    313                swImage->RowStride = rowStride;
    314             else
    315                assert(swImage->RowStride == rowStride);
    316          }
    317       }
    318    }
    319 }
    320 
    321 
    322 void
    323 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
    324 {
    325    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
    326    GLuint face, level;
    327 
    328    for (face = 0; face < faces; face++) {
    329       for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
    330          struct gl_texture_image *texImage = texObj->Image[face][level];
    331          struct swrast_texture_image *swImage = swrast_texture_image(texImage);
    332          unsigned int i, slices;
    333 
    334          if (!texImage)
    335             continue;
    336 
    337          if (swImage->Buffer)
    338             return;
    339 
    340          if (!swImage->ImageSlices)
    341             continue;
    342 
    343          slices = texture_slices(texImage);
    344 
    345          for (i = 0; i < slices; i++) {
    346             if (swImage->ImageSlices[i]) {
    347                ctx->Driver.UnmapTextureImage(ctx, texImage, i);
    348                swImage->ImageSlices[i] = NULL;
    349             }
    350          }
    351       }
    352    }
    353 }
    354 
    355 
    356 /**
    357  * Map all textures for reading prior to software rendering.
    358  */
    359 void
    360 _swrast_map_textures(struct gl_context *ctx)
    361 {
    362    int unit;
    363 
    364    for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
    365       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
    366 
    367       if (texObj)
    368          _swrast_map_texture(ctx, texObj);
    369    }
    370 }
    371 
    372 
    373 /**
    374  * Unmap all textures for reading prior to software rendering.
    375  */
    376 void
    377 _swrast_unmap_textures(struct gl_context *ctx)
    378 {
    379    int unit;
    380    for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
    381       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
    382 
    383       if (texObj)
    384          _swrast_unmap_texture(ctx, texObj);
    385    }
    386 }
    387