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 }