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 
00030 
00031 
00032 
00033 #include "pipe/p_context.h"
00034 #include "pipe/p_defines.h"
00035 #include "pipe/p_inlines.h"
00036 #include "pipe/p_winsys.h"
00037 #include "util/u_math.h"
00038 #include "util/u_memory.h"
00039 
00040 #include "sp_context.h"
00041 #include "sp_state.h"
00042 #include "sp_texture.h"
00043 #include "sp_tile_cache.h"
00044 #include "sp_screen.h"
00045 
00046 
00047 
00048 
00049 
00050 static unsigned minify( unsigned d )
00051 {
00052    return MAX2(1, d>>1);
00053 }
00054 
00055 
00056 
00057 
00058 static boolean
00059 softpipe_texture_layout(struct pipe_screen *screen,
00060                         struct softpipe_texture * spt)
00061 {
00062    struct pipe_winsys *ws = screen->winsys;
00063    struct pipe_texture *pt = &spt->base;
00064    unsigned level;
00065    unsigned width = pt->width[0];
00066    unsigned height = pt->height[0];
00067    unsigned depth = pt->depth[0];
00068 
00069    unsigned buffer_size = 0;
00070 
00071    for (level = 0; level <= pt->last_level; level++) {
00072       pt->width[level] = width;
00073       pt->height[level] = height;
00074       pt->depth[level] = depth;
00075       pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);  
00076       pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);  
00077       spt->stride[level] = pt->nblocksx[level]*pt->block.size;
00078 
00079       spt->level_offset[level] = buffer_size;
00080 
00081       buffer_size += (pt->nblocksy[level] *
00082                       ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
00083                       spt->stride[level]);
00084 
00085       width  = minify(width);
00086       height = minify(height);
00087       depth = minify(depth);
00088    }
00089 
00090    spt->buffer = ws->buffer_create(ws, 32,
00091                                    PIPE_BUFFER_USAGE_PIXEL,
00092                                    buffer_size);
00093 
00094    return spt->buffer != NULL;
00095 }
00096 
00097 
00098 
00099 
00100 static boolean
00101 softpipe_displaytarget_layout(struct pipe_screen *screen,
00102                               struct softpipe_texture * spt)
00103 {
00104    struct pipe_winsys *ws = screen->winsys;
00105    struct pipe_surface surf;
00106    unsigned flags = (PIPE_BUFFER_USAGE_CPU_READ |
00107                      PIPE_BUFFER_USAGE_CPU_WRITE |
00108                      PIPE_BUFFER_USAGE_GPU_READ |
00109                      PIPE_BUFFER_USAGE_GPU_WRITE);
00110    int ret;
00111 
00112 
00113    memset(&surf, 0, sizeof(surf));
00114 
00115    ret =ws->surface_alloc_storage( ws, 
00116                                    &surf,
00117                                    spt->base.width[0], 
00118                                    spt->base.height[0],
00119                                    spt->base.format,
00120                                    flags,
00121                                    spt->base.tex_usage);
00122    if(ret != 0)
00123       return FALSE;
00124 
00125    if (!surf.buffer) {
00126       
00127       return FALSE;
00128    }
00129 
00130    
00131 
00132    spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]);  
00133    spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]);  
00134    spt->stride[0] = surf.stride;
00135 
00136    
00137 
00138    spt->buffer = surf.buffer;
00139    surf.buffer = NULL;
00140 
00141    return spt->buffer != NULL;
00142 }
00143 
00144 
00145 
00146 
00147 
00148 static struct pipe_texture *
00149 softpipe_texture_create(struct pipe_screen *screen,
00150                         const struct pipe_texture *templat)
00151 {
00152    struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture);
00153    if (!spt)
00154       return NULL;
00155 
00156    spt->base = *templat;
00157    spt->base.refcount = 1;
00158    spt->base.screen = screen;
00159 
00160    if (spt->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
00161       if (!softpipe_displaytarget_layout(screen, spt))
00162          goto fail;
00163    }
00164    else {
00165       if (!softpipe_texture_layout(screen, spt))
00166          goto fail;
00167    }
00168     
00169    assert(spt->base.refcount == 1);
00170    return &spt->base;
00171 
00172  fail:
00173    FREE(spt);
00174    return NULL;
00175 }
00176 
00177 
00178 static struct pipe_texture *
00179 softpipe_texture_blanket(struct pipe_screen * screen,
00180                          const struct pipe_texture *base,
00181                          const unsigned *stride,
00182                          struct pipe_buffer *buffer)
00183 {
00184    struct softpipe_texture *spt;
00185    assert(screen);
00186 
00187    
00188    if (base->target != PIPE_TEXTURE_2D ||
00189        base->last_level != 0 ||
00190        base->depth[0] != 1) {
00191       return NULL;
00192    }
00193 
00194    spt = CALLOC_STRUCT(softpipe_texture);
00195    if (!spt)
00196       return NULL;
00197 
00198    spt->base = *base;
00199    spt->base.refcount = 1;
00200    spt->base.screen = screen;
00201    spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]);  
00202    spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]);  
00203    spt->stride[0] = stride[0];
00204 
00205    pipe_buffer_reference(screen, &spt->buffer, buffer);
00206 
00207    return &spt->base;
00208 }
00209 
00210 
00211 static void
00212 softpipe_texture_release(struct pipe_screen *screen,
00213                          struct pipe_texture **pt)
00214 {
00215    if (!*pt)
00216       return;
00217 
00218    if (--(*pt)->refcount <= 0) {
00219       struct softpipe_texture *spt = softpipe_texture(*pt);
00220 
00221       pipe_buffer_reference(screen, &spt->buffer, NULL);
00222       FREE(spt);
00223    }
00224    *pt = NULL;
00225 }
00226 
00227 
00228 static struct pipe_surface *
00229 softpipe_get_tex_surface(struct pipe_screen *screen,
00230                          struct pipe_texture *pt,
00231                          unsigned face, unsigned level, unsigned zslice,
00232                          unsigned usage)
00233 {
00234    struct pipe_winsys *ws = screen->winsys;
00235    struct softpipe_texture *spt = softpipe_texture(pt);
00236    struct pipe_surface *ps;
00237 
00238    assert(level <= pt->last_level);
00239 
00240    ps = CALLOC_STRUCT(pipe_surface);
00241    ps->refcount = 1;
00242    if (ps) {
00243       assert(ps->refcount);
00244       pipe_texture_reference(&ps->texture, pt);
00245       pipe_buffer_reference(screen, &ps->buffer, spt->buffer);
00246       ps->format = pt->format;
00247       ps->block = pt->block;
00248       ps->width = pt->width[level];
00249       ps->height = pt->height[level];
00250       ps->nblocksx = pt->nblocksx[level];
00251       ps->nblocksy = pt->nblocksy[level];
00252       ps->stride = spt->stride[level];
00253       ps->offset = spt->level_offset[level];
00254       ps->usage = usage;
00255       
00256       
00257 
00258 
00259 
00260 
00261       if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
00262          
00263          ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ;
00264       }
00265 
00266       if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ)
00267          ps->usage |= PIPE_BUFFER_USAGE_CPU_READ;
00268 
00269       if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE |
00270                        PIPE_BUFFER_USAGE_GPU_WRITE)) {
00271          
00272          spt->modified = TRUE;
00273       }
00274 
00275       ps->face = face;
00276       ps->level = level;
00277       ps->zslice = zslice;
00278 
00279       if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
00280          ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
00281             ps->nblocksy *
00282             ps->stride;
00283       }
00284       else {
00285          assert(face == 0);
00286          assert(zslice == 0);
00287       }
00288    }
00289    return ps;
00290 }
00291 
00292 
00293 static void 
00294 softpipe_tex_surface_release(struct pipe_screen *screen, 
00295                              struct pipe_surface **s)
00296 {
00297    struct pipe_surface *surf = *s;
00298    
00299 
00300 
00301 
00302    assert ((*s)->texture);
00303    if (--surf->refcount == 0) {
00304       pipe_texture_reference(&surf->texture, NULL); 
00305       pipe_buffer_reference(screen, &surf->buffer, NULL);
00306       FREE(surf);
00307    }
00308    *s = NULL;
00309 }
00310 
00311 
00312 static void *
00313 softpipe_surface_map( struct pipe_screen *screen,
00314                       struct pipe_surface *surface,
00315                       unsigned flags )
00316 {
00317    ubyte *map;
00318 
00319    if (flags & ~surface->usage) {
00320       assert(0);
00321       return NULL;
00322    }
00323 
00324    map = pipe_buffer_map( screen, surface->buffer, flags );
00325    if (map == NULL)
00326       return NULL;
00327 
00328    
00329 
00330 
00331    if (surface->texture &&
00332        (flags & PIPE_BUFFER_USAGE_CPU_WRITE)) 
00333    {
00334       
00335 
00336 
00337       softpipe_screen(screen)->timestamp++;
00338    }
00339    
00340    return map + surface->offset;
00341 }
00342 
00343 
00344 static void
00345 softpipe_surface_unmap(struct pipe_screen *screen,
00346                        struct pipe_surface *surface)
00347 {
00348    pipe_buffer_unmap( screen, surface->buffer );
00349 }
00350 
00351 
00352 void
00353 softpipe_init_texture_funcs(struct softpipe_context *sp)
00354 {
00355 }
00356 
00357 
00358 void
00359 softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
00360 {
00361    screen->texture_create = softpipe_texture_create;
00362    screen->texture_blanket = softpipe_texture_blanket;
00363    screen->texture_release = softpipe_texture_release;
00364 
00365    screen->get_tex_surface = softpipe_get_tex_surface;
00366    screen->tex_surface_release = softpipe_tex_surface_release;
00367 
00368    screen->surface_map = softpipe_surface_map;
00369    screen->surface_unmap = softpipe_surface_unmap;
00370 }