00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "main/imports.h"
00030 #include "main/mipmap.h"
00031 #include "main/teximage.h"
00032 #include "main/texformat.h"
00033
00034 #include "shader/prog_instruction.h"
00035
00036 #include "pipe/p_context.h"
00037 #include "pipe/p_defines.h"
00038 #include "pipe/p_inlines.h"
00039 #include "util/u_gen_mipmap.h"
00040
00041 #include "cso_cache/cso_cache.h"
00042 #include "cso_cache/cso_context.h"
00043
00044 #include "st_context.h"
00045 #include "st_draw.h"
00046 #include "st_gen_mipmap.h"
00047 #include "st_program.h"
00048 #include "st_texture.h"
00049 #include "st_cb_texture.h"
00050
00051
00057 void
00058 st_init_generate_mipmap(struct st_context *st)
00059 {
00060 st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
00061 }
00062
00063
00064 void
00065 st_destroy_generate_mipmap(struct st_context *st)
00066 {
00067 util_destroy_gen_mipmap(st->gen_mipmap);
00068 st->gen_mipmap = NULL;
00069 }
00070
00071
00076 static boolean
00077 st_render_mipmap(struct st_context *st,
00078 GLenum target,
00079 struct pipe_texture *pt,
00080 uint baseLevel, uint lastLevel)
00081 {
00082 struct pipe_context *pipe = st->pipe;
00083 struct pipe_screen *screen = pipe->screen;
00084 const uint face = _mesa_tex_target_to_face(target);
00085
00086 assert(target != GL_TEXTURE_3D);
00087
00088
00089 if (!screen->is_format_supported(screen, pt->format, target,
00090 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
00091 return FALSE;
00092 }
00093
00094 util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel,
00095 PIPE_TEX_FILTER_LINEAR);
00096
00097 return TRUE;
00098 }
00099
00100
00101 static void
00102 fallback_generate_mipmap(GLcontext *ctx, GLenum target,
00103 struct gl_texture_object *texObj)
00104 {
00105 struct pipe_context *pipe = ctx->st->pipe;
00106 struct pipe_screen *screen = pipe->screen;
00107 struct pipe_texture *pt = st_get_texobj_texture(texObj);
00108 const uint baseLevel = texObj->BaseLevel;
00109 const uint lastLevel = pt->last_level;
00110 const uint face = _mesa_tex_target_to_face(target), zslice = 0;
00111 uint dstLevel;
00112 GLenum datatype;
00113 GLuint comps;
00114
00115 assert(target != GL_TEXTURE_3D);
00116
00117 _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
00118 &datatype, &comps);
00119
00120 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
00121 const uint srcLevel = dstLevel - 1;
00122 struct pipe_surface *srcSurf, *dstSurf;
00123 const ubyte *srcData;
00124 ubyte *dstData;
00125
00126 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
00127 PIPE_BUFFER_USAGE_CPU_READ);
00128 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
00129 PIPE_BUFFER_USAGE_CPU_WRITE);
00130
00131 srcData = (ubyte *) pipe_buffer_map(pipe->screen, srcSurf->buffer,
00132 PIPE_BUFFER_USAGE_CPU_READ)
00133 + srcSurf->offset;
00134 dstData = (ubyte *) pipe_buffer_map(pipe->screen, dstSurf->buffer,
00135 PIPE_BUFFER_USAGE_CPU_WRITE)
00136 + dstSurf->offset;
00137
00138 _mesa_generate_mipmap_level(target, datatype, comps,
00139 0 ,
00140 pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
00141 srcSurf->stride,
00142 srcData,
00143 pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
00144 dstSurf->stride,
00145 dstData);
00146
00147 pipe_buffer_unmap(pipe->screen, srcSurf->buffer);
00148 pipe_buffer_unmap(pipe->screen, dstSurf->buffer);
00149
00150 pipe_surface_reference(&srcSurf, NULL);
00151 pipe_surface_reference(&dstSurf, NULL);
00152 }
00153 }
00154
00155
00156 void
00157 st_generate_mipmap(GLcontext *ctx, GLenum target,
00158 struct gl_texture_object *texObj)
00159 {
00160 struct st_context *st = ctx->st;
00161 struct pipe_texture *pt = st_get_texobj_texture(texObj);
00162 const uint baseLevel = texObj->BaseLevel;
00163 const uint lastLevel = pt->last_level;
00164 uint dstLevel;
00165
00166 if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) {
00167 fallback_generate_mipmap(ctx, target, texObj);
00168 }
00169
00170
00171 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
00172 const uint srcLevel = dstLevel - 1;
00173 const struct gl_texture_image *srcImage
00174 = _mesa_get_tex_image(ctx, texObj, target, srcLevel);
00175 struct gl_texture_image *dstImage;
00176 struct st_texture_image *stImage;
00177 uint dstWidth = pt->width[dstLevel];
00178 uint dstHeight = pt->height[dstLevel];
00179 uint dstDepth = pt->depth[dstLevel];
00180 uint border = srcImage->Border;
00181
00182 dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
00183 if (!dstImage) {
00184 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
00185 return;
00186 }
00187
00188 if (dstImage->ImageOffsets)
00189 _mesa_free(dstImage->ImageOffsets);
00190
00191
00192 if (dstImage->Data)
00193 ctx->Driver.FreeTexImageData(ctx, dstImage);
00194
00195
00196 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
00197 dstDepth, border, srcImage->InternalFormat);
00198
00199 dstImage->TexFormat = srcImage->TexFormat;
00200
00201 stImage = (struct st_texture_image *) dstImage;
00202 pipe_texture_reference(&stImage->pt, pt);
00203 }
00204 }