st_gen_mipmap.c revision c7510ddc3f6faa68154c11ce820097492a0748d2
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_surface *srcSurf, *dstSurf; 123 const ubyte *srcData; 124 ubyte *dstData; 125 126 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice, 127 PIPE_BUFFER_USAGE_CPU_READ); 128 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice, 129 PIPE_BUFFER_USAGE_CPU_WRITE); 130 131 srcData = (ubyte *) pipe_buffer_map(pipe->screen, srcSurf->buffer, 132 PIPE_BUFFER_USAGE_CPU_READ) 133 + srcSurf->offset; 134 dstData = (ubyte *) pipe_buffer_map(pipe->screen, dstSurf->buffer, 135 PIPE_BUFFER_USAGE_CPU_WRITE) 136 + dstSurf->offset; 137 138 _mesa_generate_mipmap_level(target, datatype, comps, 139 0 /*border*/, 140 pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], 141 srcData, 142 srcSurf->stride, /* stride in bytes */ 143 pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], 144 dstData, 145 dstSurf->stride); /* stride in bytes */ 146 147 pipe_buffer_unmap(pipe->screen, srcSurf->buffer); 148 pipe_buffer_unmap(pipe->screen, dstSurf->buffer); 149 150 pipe_surface_reference(&srcSurf, NULL); 151 pipe_surface_reference(&dstSurf, NULL); 152 } 153} 154 155 156void 157st_generate_mipmap(GLcontext *ctx, GLenum target, 158 struct gl_texture_object *texObj) 159{ 160 struct st_context *st = ctx->st; 161 struct pipe_texture *pt = st_get_texobj_texture(texObj); 162 const uint baseLevel = texObj->BaseLevel; 163 const uint lastLevel = pt->last_level; 164 uint dstLevel; 165 166 if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) { 167 fallback_generate_mipmap(ctx, target, texObj); 168 } 169 170 /* Fill in the Mesa gl_texture_image fields */ 171 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 172 const uint srcLevel = dstLevel - 1; 173 const struct gl_texture_image *srcImage 174 = _mesa_get_tex_image(ctx, texObj, target, srcLevel); 175 struct gl_texture_image *dstImage; 176 struct st_texture_image *stImage; 177 uint dstWidth = pt->width[dstLevel]; 178 uint dstHeight = pt->height[dstLevel]; 179 uint dstDepth = pt->depth[dstLevel]; 180 uint border = srcImage->Border; 181 182 dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); 183 if (!dstImage) { 184 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 185 return; 186 } 187 188 if (dstImage->ImageOffsets) 189 _mesa_free(dstImage->ImageOffsets); 190 191 /* Free old image data */ 192 if (dstImage->Data) 193 ctx->Driver.FreeTexImageData(ctx, dstImage); 194 195 /* initialize new image */ 196 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, 197 dstDepth, border, srcImage->InternalFormat); 198 199 dstImage->TexFormat = srcImage->TexFormat; 200 201 stImage = (struct st_texture_image *) dstImage; 202 pipe_texture_reference(&stImage->pt, pt); 203 } 204} 205