st_gen_mipmap.c revision 99fba5466bfd14c4e052041c0571821be529e762
10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong/**************************************************************************
20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong *
30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * All Rights Reserved.
50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong *
60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * Permission is hereby granted, free of charge, to any person obtaining a
70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * copy of this software and associated documentation files (the
80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * "Software"), to deal in the Software without restriction, including
90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * without limitation the rights to use, copy, modify, merge, publish,
100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * distribute, sub license, and/or sell copies of the Software, and to
110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * permit persons to whom the Software is furnished to do so, subject to
120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * the following conditions:
130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong *
140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * The above copyright notice and this permission notice (including the
150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * next paragraph) shall be included in all copies or substantial portions
160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * of the Software.
170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong *
180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong *
260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong **************************************************************************/
270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "main/imports.h"
300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "main/mipmap.h"
310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "main/teximage.h"
320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "main/texformat.h"
330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "shader/prog_instruction.h"
350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "pipe/p_context.h"
370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "pipe/p_defines.h"
380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "pipe/p_inlines.h"
390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "util/u_gen_mipmap.h"
400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "cso_cache/cso_cache.h"
420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "cso_cache/cso_context.h"
430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_context.h"
450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_draw.h"
460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_gen_mipmap.h"
470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_program.h"
480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_texture.h"
490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_cb_drawpixels.h"
500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "st_cb_texture.h"
510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong/**
540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * one-time init for generate mipmap
550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * XXX Note: there may be other times we need no-op/simple state like this.
560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * In that case, some code refactoring would be good.
570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong */
580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid
590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongst_init_generate_mipmap(struct st_context *st)
600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong{
610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid
660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongst_destroy_generate_mipmap(struct st_context *st)
670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong{
680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   util_destroy_gen_mipmap(st->gen_mipmap);
690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   st->gen_mipmap = NULL;
700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong/**
740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * Generate mipmap levels using hardware rendering.
750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong * \return TRUE if successful, FALSE if not possible
760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong */
770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongstatic boolean
780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongst_render_mipmap(struct st_context *st,
790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                 GLenum target,
800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                 struct pipe_texture *pt,
810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                 uint baseLevel, uint lastLevel)
820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong{
830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   struct pipe_context *pipe = st->pipe;
840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   struct pipe_screen *screen = pipe->screen;
850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   const uint face = _mesa_tex_target_to_face(target);
860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   assert(target != GL_TEXTURE_3D); /* not done yet */
880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   /* check if we can render in the texture's format */
900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   if (!screen->is_format_supported(screen, pt->format, PIPE_SURFACE)) {
910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return FALSE;
920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   }
930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel,
950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                   PIPE_TEX_FILTER_LINEAR);
960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   return TRUE;
980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongstatic void
1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongfallback_generate_mipmap(GLcontext *ctx, GLenum target,
1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                         struct gl_texture_object *texObj)
1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong{
1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   struct pipe_context *pipe = ctx->st->pipe;
1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   struct pipe_screen *screen = pipe->screen;
1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   struct pipe_texture *pt = st_get_texobj_texture(texObj);
1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   const uint baseLevel = texObj->BaseLevel;
1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   const uint lastLevel = pt->last_level;
1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   const uint face = _mesa_tex_target_to_face(target), zslice = 0;
1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   uint dstLevel;
1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   GLenum datatype;
1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   GLuint comps;
1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   assert(target != GL_TEXTURE_3D); /* not done yet */
1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                                  &datatype, &comps);
1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong   for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      const uint srcLevel = dstLevel - 1;
1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      struct pipe_surface *srcSurf, *dstSurf;
1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      const ubyte *srcData;
1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ubyte *dstData;
1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice);
1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      srcData = (ubyte *) pipe_buffer_map(pipe, srcSurf->buffer,
1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                                          PIPE_BUFFER_USAGE_CPU_READ)
1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong              + srcSurf->offset;
1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      dstData = (ubyte *) pipe_buffer_map(pipe, dstSurf->buffer,
1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                                          PIPE_BUFFER_USAGE_CPU_WRITE)
134              + dstSurf->offset;
135
136      _mesa_generate_mipmap_level(target, datatype, comps,
137                   0 /*border*/,
138                   pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
139                   srcSurf->pitch * srcSurf->cpp, /* stride in bytes */
140                   srcData,
141                   pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
142                   dstSurf->pitch * dstSurf->cpp, /* stride in bytes */
143                   dstData);
144
145      pipe_buffer_unmap(pipe, srcSurf->buffer);
146      pipe_buffer_unmap(pipe, dstSurf->buffer);
147
148      pipe_surface_reference(&srcSurf, NULL);
149      pipe_surface_reference(&dstSurf, NULL);
150   }
151}
152
153
154void
155st_generate_mipmap(GLcontext *ctx, GLenum target,
156                   struct gl_texture_object *texObj)
157{
158   struct st_context *st = ctx->st;
159   struct pipe_texture *pt = st_get_texobj_texture(texObj);
160   const uint baseLevel = texObj->BaseLevel;
161   const uint lastLevel = pt->last_level;
162   uint dstLevel;
163
164   if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
165      fallback_generate_mipmap(ctx, target, texObj);
166   }
167
168   /* Fill in the Mesa gl_texture_image fields */
169   for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
170      const uint srcLevel = dstLevel - 1;
171      const struct gl_texture_image *srcImage
172         = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
173      struct gl_texture_image *dstImage;
174      struct st_texture_image *stImage;
175      uint dstWidth = pt->width[dstLevel];
176      uint dstHeight = pt->height[dstLevel];
177      uint dstDepth = pt->depth[dstLevel];
178      uint border = srcImage->Border;
179
180      dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
181      if (!dstImage) {
182         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
183         return;
184      }
185
186      if (dstImage->ImageOffsets)
187         _mesa_free(dstImage->ImageOffsets);
188
189      /* Free old image data */
190      if (dstImage->Data)
191         ctx->Driver.FreeTexImageData(ctx, dstImage);
192
193      /* initialize new image */
194      _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
195                                 dstDepth, border, srcImage->InternalFormat);
196
197      dstImage->TexFormat = srcImage->TexFormat;
198
199      stImage = (struct st_texture_image *) dstImage;
200      stImage->pt = pt;
201   }
202}
203