st_texture.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 #include "st_context.h"
00029 #include "st_format.h"
00030 #include "st_public.h"
00031 #include "st_texture.h"
00032 #include "st_cb_fbo.h"
00033 #include "main/enums.h"
00034 #include "main/teximage.h"
00035 
00036 #undef Elements  /* fix re-defined macro warning */
00037 
00038 #include "pipe/p_state.h"
00039 #include "pipe/p_context.h"
00040 #include "pipe/p_defines.h"
00041 #include "pipe/p_inlines.h"
00042 #include "pipe/p_inlines.h"
00043 #include "util/u_rect.h"
00044 
00045 
00046 #define DBG if(0) printf
00047 
00048 #if 0
00049 static GLenum
00050 target_to_target(GLenum target)
00051 {
00052    switch (target) {
00053    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
00054    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
00055    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
00056    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
00057    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
00058    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
00059       return GL_TEXTURE_CUBE_MAP_ARB;
00060    default:
00061       return target;
00062    }
00063 }
00064 #endif
00065 
00066 
00073 struct pipe_texture *
00074 st_texture_create(struct st_context *st,
00075                   enum pipe_texture_target target,
00076                   enum pipe_format format,
00077                   GLuint last_level,
00078                   GLuint width0,
00079                   GLuint height0,
00080                   GLuint depth0,
00081                   GLuint compress_byte,
00082                   GLuint usage )
00083 {
00084    struct pipe_texture pt, *newtex;
00085    struct pipe_screen *screen = st->pipe->screen;
00086 
00087    assert(target <= PIPE_TEXTURE_CUBE);
00088 
00089    DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
00090        _mesa_lookup_enum_by_nr(target),
00091        _mesa_lookup_enum_by_nr(format), last_level);
00092 
00093    assert(format);
00094    assert(screen->is_format_supported(screen, format, target, 
00095                                       PIPE_TEXTURE_USAGE_SAMPLER, 0));
00096 
00097    memset(&pt, 0, sizeof(pt));
00098    pt.target = target;
00099    pt.format = format;
00100    pt.last_level = last_level;
00101    pt.width[0] = width0;
00102    pt.height[0] = height0;
00103    pt.depth[0] = depth0;
00104    pt.compressed = compress_byte ? 1 : 0;
00105    pf_get_block(format, &pt.block);
00106    pt.tex_usage = usage;
00107 
00108    newtex = screen->texture_create(screen, &pt);
00109 
00110    assert(!newtex || newtex->refcount == 1);
00111 
00112    return newtex;
00113 }
00114 
00115 
00122 GLboolean
00123 st_texture_match_image(const struct pipe_texture *pt,
00124                        const struct gl_texture_image *image,
00125                        GLuint face, GLuint level)
00126 {
00127    /* Images with borders are never pulled into mipmap textures. 
00128     */
00129    if (image->Border) 
00130       return GL_FALSE;
00131 
00132    if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format ||
00133        image->IsCompressed != pt->compressed)
00134       return GL_FALSE;
00135 
00136    /* Test image dimensions against the base level image adjusted for
00137     * minification.  This will also catch images not present in the
00138     * texture, changed targets, etc.
00139     */
00140    if (image->Width != pt->width[level] ||
00141        image->Height != pt->height[level] ||
00142        image->Depth != pt->depth[level])
00143       return GL_FALSE;
00144 
00145    return GL_TRUE;
00146 }
00147 
00148 
00149 #if 000
00150 /* Although we use the image_offset[] array to store relative offsets
00151  * to cube faces, Mesa doesn't know anything about this and expects
00152  * each cube face to be treated as a separate image.
00153  *
00154  * These functions present that view to mesa:
00155  */
00156 const GLuint *
00157 st_texture_depth_offsets(struct pipe_texture *pt, GLuint level)
00158 {
00159    static const GLuint zero = 0;
00160 
00161    if (pt->target != PIPE_TEXTURE_3D || pt->level[level].nr_images == 1)
00162       return &zero;
00163    else
00164       return pt->level[level].image_offset;
00165 }
00166 
00167 
00172 GLuint
00173 st_texture_image_offset(const struct pipe_texture * pt,
00174                         GLuint face, GLuint level)
00175 {
00176    if (pt->target == PIPE_TEXTURE_CUBE)
00177       return (pt->level[level].level_offset +
00178               pt->level[level].image_offset[face] * pt->cpp);
00179    else
00180       return pt->level[level].level_offset;
00181 }
00182 #endif
00183 
00184 
00191 GLubyte *
00192 st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
00193                      GLuint zoffset,
00194                      GLuint flags )
00195 {
00196    struct pipe_screen *screen = st->pipe->screen;
00197    struct pipe_texture *pt = stImage->pt;
00198    DBG("%s \n", __FUNCTION__);
00199 
00200    stImage->surface = screen->get_tex_surface(screen, pt, stImage->face,
00201                                               stImage->level, zoffset, 
00202                                               flags);
00203 
00204    if (stImage->surface)
00205       return screen->surface_map(screen, stImage->surface, flags);
00206    else
00207       return NULL;
00208 }
00209 
00210 
00211 void
00212 st_texture_image_unmap(struct st_context *st,
00213                        struct st_texture_image *stImage)
00214 {
00215    struct pipe_screen *screen = st->pipe->screen;
00216 
00217    DBG("%s\n", __FUNCTION__);
00218 
00219    screen->surface_unmap(screen, stImage->surface);
00220 
00221    pipe_surface_reference(&stImage->surface, NULL);
00222 }
00223 
00224 
00225 
00234 static void
00235 st_surface_data(struct pipe_context *pipe,
00236                 struct pipe_surface *dst,
00237                 unsigned dstx, unsigned dsty,
00238                 const void *src, unsigned src_stride,
00239                 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
00240 {
00241    struct pipe_screen *screen = pipe->screen;
00242    void *map = screen->surface_map(screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE);
00243 
00244    pipe_copy_rect(map,
00245                   &dst->block,
00246                   dst->stride,
00247                   dstx, dsty, 
00248                   width, height, 
00249                   src, src_stride, 
00250                   srcx, srcy);
00251 
00252    screen->surface_unmap(screen, dst);
00253 }
00254 
00255 
00256 /* Upload data for a particular image.
00257  */
00258 void
00259 st_texture_image_data(struct pipe_context *pipe,
00260                       struct pipe_texture *dst,
00261                       GLuint face,
00262                       GLuint level,
00263                       void *src,
00264                       GLuint src_row_stride, GLuint src_image_stride)
00265 {
00266    struct pipe_screen *screen = pipe->screen;
00267    GLuint depth = dst->depth[level];
00268    GLuint i;
00269    const GLubyte *srcUB = src;
00270    struct pipe_surface *dst_surface;
00271 
00272    DBG("%s\n", __FUNCTION__);
00273    for (i = 0; i < depth; i++) {
00274       dst_surface = screen->get_tex_surface(screen, dst, face, level, i,
00275                                             PIPE_BUFFER_USAGE_CPU_WRITE);
00276 
00277       st_surface_data(pipe, dst_surface,
00278                       0, 0,                             /* dstx, dsty */
00279                       srcUB,
00280                       src_row_stride,
00281                       0, 0,                             /* source x, y */
00282                       dst->width[level], dst->height[level]);       /* width, height */
00283 
00284       screen->tex_surface_release(screen, &dst_surface);
00285 
00286       srcUB += src_image_stride;
00287    }
00288 }
00289 
00290 
00291 /* Copy mipmap image between textures
00292  */
00293 void
00294 st_texture_image_copy(struct pipe_context *pipe,
00295                       struct pipe_texture *dst, GLuint dstLevel,
00296                       struct pipe_texture *src,
00297                       GLuint face)
00298 {
00299    struct pipe_screen *screen = pipe->screen;
00300    GLuint width = dst->width[dstLevel];
00301    GLuint height = dst->height[dstLevel];
00302    GLuint depth = dst->depth[dstLevel];
00303    struct pipe_surface *src_surface;
00304    struct pipe_surface *dst_surface;
00305    GLuint i;
00306 
00307    for (i = 0; i < depth; i++) {
00308       GLuint srcLevel;
00309 
00310       /* find src texture level of needed size */
00311       for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) {
00312          if (src->width[srcLevel] == width &&
00313              src->height[srcLevel] == height) {
00314             break;
00315          }
00316       }
00317       assert(src->width[srcLevel] == width);
00318       assert(src->height[srcLevel] == height);
00319 
00320 #if 0
00321       {
00322          src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
00323                                                PIPE_BUFFER_USAGE_CPU_READ);
00324          ubyte *map = screen->surface_map(screen, src_surface, PIPE_BUFFER_USAGE_CPU_READ);
00325          map += src_surface->width * src_surface->height * 4 / 2;
00326          printf("%s center pixel: %d %d %d %d (pt %p[%d] -> %p[%d])\n",
00327                 __FUNCTION__,
00328                 map[0], map[1], map[2], map[3],
00329                 src, srcLevel, dst, dstLevel);
00330 
00331          screen->surface_unmap(screen, src_surface);
00332          pipe_surface_reference(&src_surface, NULL);
00333       }
00334 #endif
00335 
00336       dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i,
00337                                             PIPE_BUFFER_USAGE_GPU_WRITE);
00338 
00339       src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
00340                                             PIPE_BUFFER_USAGE_GPU_READ);
00341 
00342       pipe->surface_copy(pipe,
00343                          FALSE,
00344                          dst_surface,
00345                          0, 0, /* destX, Y */
00346                          src_surface,
00347                          0, 0, /* srcX, Y */
00348                          width, height);
00349 
00350       screen->tex_surface_release(screen, &src_surface);
00351       screen->tex_surface_release(screen, &dst_surface);
00352    }
00353 }
00354 
00355 
00357 int
00358 st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
00359                  int target, int format, int level)
00360 {
00361    GET_CURRENT_CONTEXT(ctx);
00362    struct st_context *st = ctx->st;
00363    struct pipe_context *pipe = st->pipe;
00364    struct pipe_screen *screen = pipe->screen;
00365    const GLuint unit = ctx->Texture.CurrentUnit;
00366    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
00367    struct gl_texture_object *texObj;
00368    struct gl_texture_image *texImage;
00369    struct st_texture_image *stImage;
00370    struct st_renderbuffer *strb;
00371    GLint face = 0, slice = 0;
00372 
00373    assert(surfIndex <= ST_SURFACE_DEPTH);
00374 
00375    strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00376 
00377    if (strb->texture_save || strb->surface_save) {
00378       /* Error! */
00379       return 0;
00380    }
00381 
00382    if (target == ST_TEXTURE_2D) {
00383       texObj = texUnit->Current2D;
00384       texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level);
00385       stImage = st_texture_image(texImage);
00386    }
00387    else {
00388       /* unsupported target */
00389       return 0;
00390    }
00391 
00392    st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
00393 
00394    /* save the renderbuffer's surface/texture info */
00395    pipe_texture_reference(&strb->texture_save, strb->texture);
00396    pipe_surface_reference(&strb->surface_save, strb->surface);
00397 
00398    /* plug in new surface/texture info */
00399    pipe_texture_reference(&strb->texture, stImage->pt);
00400    strb->surface = screen->get_tex_surface(screen, strb->texture,
00401                                            face, level, slice,
00402                                            (PIPE_BUFFER_USAGE_GPU_READ |
00403                                             PIPE_BUFFER_USAGE_GPU_WRITE));
00404 
00405    st->dirty.st |= ST_NEW_FRAMEBUFFER;
00406 
00407    return 1;
00408 }
00409 
00410 
00412 int
00413 st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
00414                     int target, int format, int level)
00415 {
00416    GET_CURRENT_CONTEXT(ctx);
00417    struct st_context *st = ctx->st;
00418    struct st_renderbuffer *strb;
00419 
00420    assert(surfIndex <= ST_SURFACE_DEPTH);
00421 
00422    strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00423 
00424    if (!strb->texture_save || !strb->surface_save) {
00425       /* Error! */
00426       return 0;
00427    }
00428 
00429    st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
00430 
00431    /* free tex surface, restore original */
00432    pipe_surface_reference(&strb->surface, strb->surface_save);
00433    pipe_texture_reference(&strb->texture, strb->texture_save);
00434 
00435    pipe_surface_reference(&strb->surface_save, NULL);
00436    pipe_texture_reference(&strb->texture_save, NULL);
00437 
00438    st->dirty.st |= ST_NEW_FRAMEBUFFER;
00439 
00440    return 1;
00441 }

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4