static void fallback_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; const uint lastLevel = pt->last_level; const uint face = _mesa_tex_target_to_face(target), zslice = 0; uint dstLevel; GLenum datatype; GLuint comps; assert(target != GL_TEXTURE_3D); /* not done yet */ _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, &datatype, &comps); for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; struct pipe_transfer *srcTrans, *dstTrans; const ubyte *srcData; ubyte *dstData; int srcStride, dstStride; srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, srcLevel, zslice, PIPE_TRANSFER_READ, 0, 0, pt->width[srcLevel], pt->height[srcLevel]); dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, dstLevel, zslice, PIPE_TRANSFER_WRITE, 0, 0, pt->width[dstLevel], pt->height[dstLevel]); srcData = (ubyte *) screen->transfer_map(screen, srcTrans); dstData = (ubyte *) screen->transfer_map(screen, dstTrans); srcStride = srcTrans->stride / srcTrans->block.size; dstStride = dstTrans->stride / dstTrans->block.size; _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], srcData, srcStride, /* stride in texels */ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], dstData, dstStride); /* stride in texels */ screen->transfer_unmap(screen, srcTrans); screen->transfer_unmap(screen, dstTrans); screen->tex_transfer_destroy(srcTrans); screen->tex_transfer_destroy(dstTrans); } }
/** * Software fallback for generate mipmap levels. */ static void fallback_generate_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct pipe_context *pipe = st_context(ctx)->pipe; struct pipe_resource *pt = st_get_texobj_resource(texObj); const uint baseLevel = texObj->BaseLevel; const uint lastLevel = pt->last_level; const uint face = _mesa_tex_target_to_face(target); uint dstLevel; GLenum datatype; GLuint comps; GLboolean compressed; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); assert(target != GL_TEXTURE_3D); /* not done yet */ compressed = _mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat); if (compressed) { GLenum type = _mesa_get_format_datatype(texObj->Image[face][baseLevel]->TexFormat); datatype = type == GL_UNSIGNED_NORMALIZED ? GL_UNSIGNED_BYTE : GL_FLOAT; comps = 4; } else { _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, &datatype, &comps); assert(comps > 0 && "bad texture format in fallback_generate_mipmap()"); } for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; const uint srcWidth = u_minify(pt->width0, srcLevel); const uint srcHeight = u_minify(pt->height0, srcLevel); const uint srcDepth = u_minify(pt->depth0, srcLevel); const uint dstWidth = u_minify(pt->width0, dstLevel); const uint dstHeight = u_minify(pt->height0, dstLevel); const uint dstDepth = u_minify(pt->depth0, dstLevel); struct pipe_transfer *srcTrans, *dstTrans; const ubyte *srcData; ubyte *dstData; int srcStride, dstStride; srcTrans = pipe_get_transfer(pipe, pt, srcLevel, face, PIPE_TRANSFER_READ, 0, 0, srcWidth, srcHeight); dstTrans = pipe_get_transfer(pipe, pt, dstLevel, face, PIPE_TRANSFER_WRITE, 0, 0, dstWidth, dstHeight); srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans); dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans); srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format); dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format); /* this cannot work correctly for 3d since it does not respect layerStride. */ if (compressed) { const enum pipe_format format = pt->format; const uint bw = util_format_get_blockwidth(format); const uint bh = util_format_get_blockheight(format); const uint srcWidth2 = align(srcWidth, bw); const uint srcHeight2 = align(srcHeight, bh); const uint dstWidth2 = align(dstWidth, bw); const uint dstHeight2 = align(dstHeight, bh); uint8_t *srcTemp, *dstTemp; assert(comps == 4); srcTemp = malloc(srcWidth2 * srcHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); dstTemp = malloc(dstWidth2 * dstHeight2 * comps * (datatype == GL_FLOAT ? 4 : 1)); /* decompress the src image: srcData -> srcTemp */ decompress_image(format, datatype, srcData, srcTemp, srcWidth2, srcHeight2, srcTrans->stride); _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, srcWidth2, srcHeight2, srcDepth, srcTemp, srcWidth2, /* stride in texels */ dstWidth2, dstHeight2, dstDepth, dstTemp, dstWidth2); /* stride in texels */ /* compress the new image: dstTemp -> dstData */ compress_image(format, datatype, dstTemp, dstData, dstWidth2, dstHeight2, dstTrans->stride); free(srcTemp); free(dstTemp); } else { _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, srcWidth, srcHeight, srcDepth, srcData, srcStride, /* stride in texels */ dstWidth, dstHeight, dstDepth, dstData, dstStride); /* stride in texels */ } pipe_transfer_unmap(pipe, srcTrans); pipe_transfer_unmap(pipe, dstTrans); pipe->transfer_destroy(pipe, srcTrans); pipe->transfer_destroy(pipe, dstTrans); } }