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 "cell_context.h"
00041 #include "cell_state.h"
00042 #include "cell_texture.h"
00043
00044
00045
00046
00047
00048 static unsigned minify( unsigned d )
00049 {
00050 return MAX2(1, d>>1);
00051 }
00052
00053
00054 static void
00055 cell_texture_layout(struct cell_texture * spt)
00056 {
00057 struct pipe_texture *pt = &spt->base;
00058 unsigned level;
00059 unsigned width = pt->width[0];
00060 unsigned height = pt->height[0];
00061 unsigned depth = pt->depth[0];
00062
00063 spt->buffer_size = 0;
00064
00065 for ( level = 0 ; level <= pt->last_level ; level++ ) {
00066 unsigned size;
00067 unsigned w_tile, h_tile;
00068
00069
00070 w_tile = align(width, TILE_SIZE);
00071 h_tile = align(height, TILE_SIZE);
00072
00073 pt->width[level] = width;
00074 pt->height[level] = height;
00075 pt->depth[level] = depth;
00076 pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w_tile);
00077 pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h_tile);
00078
00079 spt->stride[level] = pt->nblocksx[level] * pt->block.size;
00080
00081 spt->level_offset[level] = spt->buffer_size;
00082
00083 size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size;
00084 if (pt->target == PIPE_TEXTURE_CUBE)
00085 size *= 6;
00086 else
00087 size *= depth;
00088
00089 spt->buffer_size += size;
00090
00091 width = minify(width);
00092 height = minify(height);
00093 depth = minify(depth);
00094 }
00095 }
00096
00097
00098 static struct pipe_texture *
00099 cell_texture_create(struct pipe_screen *screen,
00100 const struct pipe_texture *templat)
00101 {
00102 struct pipe_winsys *ws = screen->winsys;
00103 struct cell_texture *spt = CALLOC_STRUCT(cell_texture);
00104 if (!spt)
00105 return NULL;
00106
00107 spt->base = *templat;
00108 spt->base.refcount = 1;
00109 spt->base.screen = screen;
00110
00111 cell_texture_layout(spt);
00112
00113 spt->buffer = ws->buffer_create(ws, 32,
00114 PIPE_BUFFER_USAGE_PIXEL,
00115 spt->buffer_size);
00116
00117 if (!spt->buffer) {
00118 FREE(spt);
00119 return NULL;
00120 }
00121
00122 return &spt->base;
00123 }
00124
00125
00126 static void
00127 cell_texture_release(struct pipe_screen *screen,
00128 struct pipe_texture **pt)
00129 {
00130 if (!*pt)
00131 return;
00132
00133
00134
00135
00136
00137 if (--(*pt)->refcount <= 0) {
00138 struct cell_texture *spt = cell_texture(*pt);
00139
00140
00141
00142
00143
00144 pipe_buffer_reference(screen, &spt->buffer, NULL);
00145
00146 FREE(spt);
00147 }
00148 *pt = NULL;
00149 }
00150
00151
00152 #if 0
00153 static void
00154 cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
00155 uint face, uint levelsMask)
00156 {
00157
00158
00159 }
00160 #endif
00161
00162
00163 static struct pipe_surface *
00164 cell_get_tex_surface(struct pipe_screen *screen,
00165 struct pipe_texture *pt,
00166 unsigned face, unsigned level, unsigned zslice,
00167 unsigned usage)
00168 {
00169 struct pipe_winsys *ws = screen->winsys;
00170 struct cell_texture *spt = cell_texture(pt);
00171 struct pipe_surface *ps;
00172
00173 ps = ws->surface_alloc(ws);
00174 if (ps) {
00175 assert(ps->refcount);
00176 assert(ps->winsys);
00177 winsys_buffer_reference(ws, &ps->buffer, spt->buffer);
00178 ps->format = pt->format;
00179 ps->block = pt->block;
00180 ps->width = pt->width[level];
00181 ps->height = pt->height[level];
00182 ps->nblocksx = pt->nblocksx[level];
00183 ps->nblocksy = pt->nblocksy[level];
00184 ps->stride = spt->stride[level];
00185 ps->offset = spt->level_offset[level];
00186 ps->usage = usage;
00187
00188
00189
00190 pipe_texture_reference(&ps->texture, pt);
00191 ps->face = face;
00192 ps->level = level;
00193 ps->zslice = zslice;
00194
00195 if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
00196 ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
00197 ps->nblocksy *
00198 ps->stride;
00199 }
00200 else {
00201 assert(face == 0);
00202 assert(zslice == 0);
00203 }
00204 }
00205 return ps;
00206 }
00207
00208
00209
00215 static void
00216 tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
00217 {
00218 const uint tile_size2 = tile_size * tile_size;
00219 const uint h_t = h / tile_size, w_t = w / tile_size;
00220
00221 uint it, jt;
00222 uint i, j;
00223
00224
00225 for (it = 0; it < h_t; it++) {
00226 for (jt = 0; jt < w_t; jt++) {
00227
00228 uint *tdst = dst + (it * w_t + jt) * tile_size2;
00229
00230 for (i = 0; i < tile_size; i++) {
00231 for (j = 0; j < tile_size; j++) {
00232 const uint srci = it * tile_size + i;
00233 const uint srcj = jt * tile_size + j;
00234 *tdst++ = src[srci * w + srcj];
00235 }
00236 }
00237 }
00238 }
00239 }
00240
00241
00242
00247 static void
00248 cell_tile_texture(struct cell_context *cell,
00249 struct cell_texture *texture)
00250 {
00251 struct pipe_screen *screen = cell->pipe.screen;
00252 uint face = 0, level = 0, zslice = 0;
00253 struct pipe_surface *surf;
00254 const uint w = texture->base.width[0], h = texture->base.height[0];
00255 const uint *src;
00256
00257
00258 assert(w >= TILE_SIZE);
00259 assert(h >= TILE_SIZE);
00260 assert(w % TILE_SIZE == 0);
00261 assert(h % TILE_SIZE == 0);
00262
00263 surf = screen->get_tex_surface(screen, &texture->base, face, level, zslice,
00264 PIPE_BUFFER_USAGE_CPU_WRITE);
00265 ASSERT(surf);
00266
00267 src = (const uint *) pipe_surface_map(surf, PIPE_BUFFER_USAGE_CPU_WRITE);
00268
00269 if (texture->tiled_data) {
00270 align_free(texture->tiled_data);
00271 }
00272 texture->tiled_data = align_malloc(w * h * 4, 16);
00273
00274 tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src);
00275
00276 pipe_surface_unmap(surf);
00277
00278 pipe_surface_reference(&surf, NULL);
00279 }
00280
00281
00282 void
00283 cell_update_texture_mapping(struct cell_context *cell)
00284 {
00285 #if 0
00286 uint face = 0, level = 0, zslice = 0;
00287 #endif
00288 uint i;
00289
00290 for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
00291 if (cell->texture[i])
00292 cell_tile_texture(cell, cell->texture[i]);
00293 }
00294
00295 #if 0
00296 if (cell->tex_surf && cell->tex_map) {
00297 pipe_surface_unmap(cell->tex_surf);
00298 cell->tex_map = NULL;
00299 }
00300
00301
00302
00303 cell->tex_surf = cell_get_tex_surface(&cell->pipe,
00304 &cell->texture[0]->base,
00305 face, level, zslice);
00306
00307 cell->tex_map = pipe_surface_map(cell->tex_surf);
00308 #endif
00309 }
00310
00311
00312 static void
00313 cell_tex_surface_release(struct pipe_screen *screen,
00314 struct pipe_surface **s)
00315 {
00316
00317
00318
00319
00320 assert ((*s)->texture);
00321 pipe_texture_reference(&(*s)->texture, NULL);
00322
00323 screen->winsys->surface_release(screen->winsys, s);
00324 }
00325
00326
00327 static void *
00328 cell_surface_map( struct pipe_screen *screen,
00329 struct pipe_surface *surface,
00330 unsigned flags )
00331 {
00332 ubyte *map;
00333
00334 if (flags & ~surface->usage) {
00335 assert(0);
00336 return NULL;
00337 }
00338
00339 map = pipe_buffer_map( screen, surface->buffer, flags );
00340 if (map == NULL)
00341 return NULL;
00342
00343
00344
00345
00346 if (surface->texture &&
00347 (flags & PIPE_BUFFER_USAGE_CPU_WRITE))
00348 {
00349
00350
00351
00352 #if 0
00353 cell_screen(screen)->timestamp++;
00354 #endif
00355 }
00356
00357 return map + surface->offset;
00358 }
00359
00360
00361 static void
00362 cell_surface_unmap(struct pipe_screen *screen,
00363 struct pipe_surface *surface)
00364 {
00365 pipe_buffer_unmap( screen, surface->buffer );
00366 }
00367
00368
00369 void
00370 cell_init_texture_functions(struct cell_context *cell)
00371 {
00372
00373 }
00374
00375
00376 void
00377 cell_init_screen_texture_funcs(struct pipe_screen *screen)
00378 {
00379 screen->texture_create = cell_texture_create;
00380 screen->texture_release = cell_texture_release;
00381
00382 screen->get_tex_surface = cell_get_tex_surface;
00383 screen->tex_surface_release = cell_tex_surface_release;
00384
00385 screen->surface_map = cell_surface_map;
00386 screen->surface_unmap = cell_surface_unmap;
00387 }