st_gen_mipmap.c revision 4ddd65967915ca4846f2831bc676c878a29dae4a
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, PIPE_SURFACE)) { 90 return FALSE; 91 } 92 93 util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel, 94 PIPE_TEX_FILTER_LINEAR); 95 96 return TRUE; 97} 98 99 100static void 101fallback_generate_mipmap(GLcontext *ctx, GLenum target, 102 struct gl_texture_object *texObj) 103{ 104 struct pipe_context *pipe = ctx->st->pipe; 105 struct pipe_screen *screen = pipe->screen; 106 struct pipe_texture *pt = st_get_texobj_texture(texObj); 107 const uint baseLevel = texObj->BaseLevel; 108 const uint lastLevel = pt->last_level; 109 const uint face = _mesa_tex_target_to_face(target), zslice = 0; 110 uint dstLevel; 111 GLenum datatype; 112 GLuint comps; 113 114 assert(target != GL_TEXTURE_3D); /* not done yet */ 115 116 _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat, 117 &datatype, &comps); 118 119 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 120 const uint srcLevel = dstLevel - 1; 121 struct pipe_surface *srcSurf, *dstSurf; 122 const ubyte *srcData; 123 ubyte *dstData; 124 125 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice, 126 PIPE_BUFFER_USAGE_CPU_READ); 127 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice, 128 PIPE_BUFFER_USAGE_CPU_WRITE); 129 130 srcData = (ubyte *) pipe_buffer_map(pipe, srcSurf->buffer, 131 PIPE_BUFFER_USAGE_CPU_READ) 132 + srcSurf->offset; 133 dstData = (ubyte *) pipe_buffer_map(pipe, dstSurf->buffer, 134 PIPE_BUFFER_USAGE_CPU_WRITE) 135 + dstSurf->offset; 136 137 _mesa_generate_mipmap_level(target, datatype, comps, 138 0 /*border*/, 139 pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], 140 srcSurf->stride, /* stride in bytes */ 141 srcData, 142 pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], 143 dstSurf->stride, /* stride in bytes */ 144 dstData); 145 146 pipe_buffer_unmap(pipe, srcSurf->buffer); 147 pipe_buffer_unmap(pipe, dstSurf->buffer); 148 149 pipe_surface_reference(&srcSurf, NULL); 150 pipe_surface_reference(&dstSurf, NULL); 151 } 152} 153 154 155void 156st_generate_mipmap(GLcontext *ctx, GLenum target, 157 struct gl_texture_object *texObj) 158{ 159 struct st_context *st = ctx->st; 160 struct pipe_texture *pt = st_get_texobj_texture(texObj); 161 const uint baseLevel = texObj->BaseLevel; 162 const uint lastLevel = pt->last_level; 163 uint dstLevel; 164 165 if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) { 166 fallback_generate_mipmap(ctx, target, texObj); 167 } 168 169 /* Fill in the Mesa gl_texture_image fields */ 170 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { 171 const uint srcLevel = dstLevel - 1; 172 const struct gl_texture_image *srcImage 173 = _mesa_get_tex_image(ctx, texObj, target, srcLevel); 174 struct gl_texture_image *dstImage; 175 struct st_texture_image *stImage; 176 uint dstWidth = pt->width[dstLevel]; 177 uint dstHeight = pt->height[dstLevel]; 178 uint dstDepth = pt->depth[dstLevel]; 179 uint border = srcImage->Border; 180 181 dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); 182 if (!dstImage) { 183 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 184 return; 185 } 186 187 if (dstImage->ImageOffsets) 188 _mesa_free(dstImage->ImageOffsets); 189 190 /* Free old image data */ 191 if (dstImage->Data) 192 ctx->Driver.FreeTexImageData(ctx, dstImage); 193 194 /* initialize new image */ 195 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, 196 dstDepth, border, srcImage->InternalFormat); 197 198 dstImage->TexFormat = srcImage->TexFormat; 199 200 stImage = (struct st_texture_image *) dstImage; 201 pipe_texture_reference(&stImage->pt, pt); 202 } 203} 204