summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker/st_gen_mipmap.c
diff options
context:
space:
mode:
authorBrian <brian.paul@tungstengraphics.com>2008-02-11 09:42:02 -0700
committerBrian <brian.paul@tungstengraphics.com>2008-02-11 09:46:50 -0700
commite4026167d70f0aa0bc0cd2546ef9b41f7b167735 (patch)
treeeb837d4c84a4e9b6fadce765d41fce480aae41f5 /src/mesa/state_tracker/st_gen_mipmap.c
parent212b27d33f94eeb25ba9cbc58f9e41295a29d2c9 (diff)
gallium: implement software fallback for mipmap generation
This is used when we can't render to the surface type of the texture (such as luminance/alpha).
Diffstat (limited to 'src/mesa/state_tracker/st_gen_mipmap.c')
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
index a6ac9a55fb..5c00392af7 100644
--- a/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -29,11 +29,14 @@
#include "main/imports.h"
#include "main/mipmap.h"
#include "main/teximage.h"
+#include "main/texformat.h"
#include "shader/prog_instruction.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
#include "pipe/cso_cache/cso_cache.h"
#include "st_context.h"
@@ -239,15 +242,18 @@ draw_quad(GLcontext *ctx)
*/
static boolean
st_render_mipmap(struct st_context *st,
+ GLenum target,
struct pipe_texture *pt,
uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = st->pipe;
struct pipe_framebuffer_state fb;
- const uint face = 0, zslice = 0;
+ const uint face = _mesa_tex_target_to_face(target), zslice = 0;
const uint first_level_save = pt->first_level;
uint dstLevel;
+ assert(target != GL_TEXTURE_3D); /* not done yet */
+
/* check if we can render in the texture's format */
if (!pipe->is_format_supported(pipe, pt->format, PIPE_SURFACE)) {
return FALSE;
@@ -307,6 +313,56 @@ st_render_mipmap(struct st_context *st,
}
+static void
+fallback_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_winsys *ws = pipe->winsys;
+ 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_surface *srcSurf, *dstSurf;
+ const ubyte *srcData;
+ ubyte *dstData;
+
+ srcSurf = pipe->get_tex_surface(pipe, pt, face, srcLevel, zslice);
+ dstSurf = pipe->get_tex_surface(pipe, pt, face, dstLevel, zslice);
+
+ srcData = (ubyte *) ws->buffer_map(ws, srcSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ)
+ + srcSurf->offset;
+ dstData = (ubyte *) ws->buffer_map(ws, dstSurf->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE)
+ + dstSurf->offset;
+
+ _mesa_generate_mipmap_level(target, datatype, comps,
+ 0 /*border*/,
+ pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
+ srcData,
+ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
+ dstData);
+
+ ws->buffer_unmap(ws, srcSurf->buffer);
+ ws->buffer_unmap(ws, dstSurf->buffer);
+
+ pipe_surface_reference(&srcSurf, NULL);
+ pipe_surface_reference(&dstSurf, NULL);
+ }
+}
+
void
st_generate_mipmap(GLcontext *ctx, GLenum target,
@@ -318,13 +374,11 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,
const uint lastLevel = pt->last_level;
uint dstLevel;
- if (!st_render_mipmap(st, pt, baseLevel, lastLevel)) {
- abort();
- /* XXX the following won't really work at this time */
- _mesa_generate_mipmap(ctx, target, texObj);
- return;
+ if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
+ fallback_generate_mipmap(ctx, target, texObj);
}
+ /* Fill in the Mesa gl_texture_image fields */
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
const struct gl_texture_image *srcImage
@@ -336,7 +390,6 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,
uint dstDepth = pt->depth[dstLevel];
uint border = srcImage->Border;
-
dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
if (!dstImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
@@ -359,5 +412,4 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,
stImage = (struct st_texture_image *) dstImage;
stImage->pt = pt;
}
-
}