st_gen_mipmap.c revision 9b75627fab5bf2ea90f27ddd31b60c54895f6de6
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29#include "main/imports.h" 30#include "main/mipmap.h" 31#include "main/teximage.h" 32#include "main/texformat.h" 33 34#include "shader/prog_instruction.h" 35 36#include "pipe/p_context.h" 37#include "pipe/p_defines.h" 38#include "pipe/p_inlines.h" 39#include "util/u_gen_mipmap.h" 40 41#include "cso_cache/cso_cache.h" 42#include "cso_cache/cso_context.h" 43 44#include "st_context.h" 45#include "st_draw.h" 46#include "st_gen_mipmap.h" 47#include "st_program.h" 48#include "st_texture.h" 49#include "st_cb_texture.h" 50 51 52/** 53 * one-time init for generate mipmap 54 * XXX Note: there may be other times we need no-op/simple state like this. 55 * In that case, some code refactoring would be good. 56 */ 57void 58st_init_generate_mipmap(struct st_context *st) 59{ 60 st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context); 61} 62 63 64void 65st_destroy_generate_mipmap(struct st_context *st) 66{ 67 util_destroy_gen_mipmap(st->gen_mipmap); 68 st->gen_mipmap = NULL; 69} 70 71 72/** 73 * Generate mipmap levels using hardware rendering. 74 * \return TRUE if successful, FALSE if not possible 75 */ 76static boolean 77st_render_mipmap(struct st_context *st, 78 GLenum target, 79 struct pipe_texture *pt, 80 uint baseLevel, uint lastLevel) 81{ 82 struct pipe_context *pipe = st->pipe; 83 struct pipe_screen *screen = pipe->screen; 84 const uint face = _mesa_tex_target_to_face(target); 85 86 assert(target != GL_TEXTURE_3D); /* not done yet */ 87 88 /* check if we can render in the texture's format */ 89 if (!screen->is_format_supported(screen, pt->format, target, 90 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { 91 return FALSE; 92 } 93 94 util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel, 95 PIPE_TEX_FILTER_LINEAR); 96 97 return TRUE; 98} 99 100 101static void 102fallback_generate_mipmap(GLcontext *ctx, GLenum target, 103 struct gl_texture_object *texObj) 104{ 105 struct pipe_context *pipe = ctx->st->pipe; 106 struct pipe_screen *screen = pipe->screen; 107 struct pipe_texture *pt = st_get_texobj_texture(texObj); 108 const uint baseLevel = texObj->BaseLevel; 109 const uint lastLevel = pt->last_level; 110 const uint face = _mesa_tex_target_to_face(target), zslice = 0; 111 uint dstLevel; 112 GLenum datatype; 113 GLuint comps; 114 115 assert(target != GL_TEXTURE_3D); /* not done yet */ 116 117 _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, 118 &datatype, &comps); 119 120 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 121 const uint srcLevel = dstLevel - 1; 122 struct pipe_transfer *srcTrans, *dstTrans; 123 const ubyte *srcData; 124 ubyte *dstData; 125 126 st_teximage_flush_before_map(ctx->st, pt, face, srcLevel, 127 PIPE_TRANSFER_READ); 128 129 srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice, 130 PIPE_TRANSFER_READ, 0, 0, 131 pt->width[srcLevel], 132 pt->height[srcLevel]); 133 134 st_teximage_flush_before_map(ctx->st, pt, face, dstLevel, 135 PIPE_TRANSFER_WRITE); 136 137 dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice, 138 PIPE_TRANSFER_WRITE, 0, 0, 139 pt->width[dstLevel], 140 pt->height[dstLevel]); 141 142 srcData = (ubyte *) screen->transfer_map(screen, srcTrans); 143 dstData = (ubyte *) screen->transfer_map(screen, dstTrans); 144 145 _mesa_generate_mipmap_level(target, datatype, comps, 146 0 /*border*/, 147 pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], 148 srcData, 149 srcTrans->stride, /* stride in bytes */ 150 pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], 151 dstData, 152 dstTrans->stride); /* stride in bytes */ 153 154 screen->transfer_unmap(screen, srcTrans); 155 screen->transfer_unmap(screen, dstTrans); 156 157 screen->tex_transfer_destroy(srcTrans); 158 screen->tex_transfer_destroy(dstTrans); 159 } 160} 161 162 163void 164st_generate_mipmap(GLcontext *ctx, GLenum target, 165 struct gl_texture_object *texObj) 166{ 167 struct st_context *st = ctx->st; 168 struct pipe_texture *pt = st_get_texobj_texture(texObj); 169 const uint baseLevel = texObj->BaseLevel; 170 uint lastLevel; 171 uint dstLevel; 172 173 if (!pt) 174 return; 175 176 lastLevel = pt->last_level; 177 178 if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) { 179 fallback_generate_mipmap(ctx, target, texObj); 180 } 181 182 /* Fill in the Mesa gl_texture_image fields */ 183 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 184 const uint srcLevel = dstLevel - 1; 185 const struct gl_texture_image *srcImage 186 = _mesa_get_tex_image(ctx, texObj, target, srcLevel); 187 struct gl_texture_image *dstImage; 188 struct st_texture_image *stImage; 189 uint dstWidth = pt->width[dstLevel]; 190 uint dstHeight = pt->height[dstLevel]; 191 uint dstDepth = pt->depth[dstLevel]; 192 uint border = srcImage->Border; 193 194 dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); 195 if (!dstImage) { 196 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 197 return; 198 } 199 200 if (dstImage->ImageOffsets) 201 _mesa_free(dstImage->ImageOffsets); 202 203 /* Free old image data */ 204 if (dstImage->Data) 205 ctx->Driver.FreeTexImageData(ctx, dstImage); 206 207 /* initialize new image */ 208 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, 209 dstDepth, border, srcImage->InternalFormat); 210 211 dstImage->TexFormat = srcImage->TexFormat; 212 213 stImage = (struct st_texture_image *) dstImage; 214 pipe_texture_reference(&stImage->pt, pt); 215 } 216} 217