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
00034
00035
00036 #include "pipe/p_state.h"
00037 #include "pipe/p_context.h"
00038 #include "pipe/p_defines.h"
00039 #include "pipe/p_inlines.h"
00040 #include "pipe/p_winsys.h"
00041 #include "util/u_math.h"
00042 #include "util/u_memory.h"
00043 #include "brw_context.h"
00044 #include "brw_tex_layout.h"
00045
00046
00047 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
00048
00049 #if 0
00050 unsigned intel_compressed_alignment(unsigned internalFormat)
00051 {
00052 unsigned alignment = 4;
00053
00054 switch (internalFormat) {
00055 case GL_COMPRESSED_RGB_FXT1_3DFX:
00056 case GL_COMPRESSED_RGBA_FXT1_3DFX:
00057 alignment = 8;
00058 break;
00059
00060 default:
00061 break;
00062 }
00063
00064 return alignment;
00065 }
00066 #endif
00067
00068 static unsigned minify( unsigned d )
00069 {
00070 return MAX2(1, d>>1);
00071 }
00072
00073
00074 static void intel_miptree_set_image_offset(struct brw_texture *tex,
00075 unsigned level,
00076 unsigned img,
00077 unsigned x, unsigned y)
00078 {
00079 struct pipe_texture *pt = &tex->base;
00080 if (img == 0 && level == 0)
00081 assert(x == 0 && y == 0);
00082 assert(img < tex->nr_images[level]);
00083
00084 tex->image_offset[level][img] = y * tex->stride + x * pt->block.size;
00085 }
00086
00087 static void intel_miptree_set_level_info(struct brw_texture *tex,
00088 unsigned level,
00089 unsigned nr_images,
00090 unsigned x, unsigned y,
00091 unsigned w, unsigned h, unsigned d)
00092 {
00093 struct pipe_texture *pt = &tex->base;
00094
00095 assert(level < PIPE_MAX_TEXTURE_LEVELS);
00096
00097 pt->width[level] = w;
00098 pt->height[level] = h;
00099 pt->depth[level] = d;
00100
00101 pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w);
00102 pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h);
00103
00104 tex->level_offset[level] = y * tex->stride + x * tex->base.block.size;
00105 tex->nr_images[level] = nr_images;
00106
00107
00108
00109
00110
00111
00112
00113
00114 if (tex->image_offset[level]) {
00115 FREE(tex->image_offset[level]);
00116 tex->image_offset[level] = NULL;
00117 }
00118
00119 assert(nr_images);
00120 assert(!tex->image_offset[level]);
00121
00122 tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
00123 tex->image_offset[level][0] = 0;
00124 }
00125
00126 static void i945_miptree_layout_2d(struct brw_texture *tex)
00127 {
00128 struct pipe_texture *pt = &tex->base;
00129 const int align_x = 2, align_y = 4;
00130 unsigned level;
00131 unsigned x = 0;
00132 unsigned y = 0;
00133 unsigned width = pt->width[0];
00134 unsigned height = pt->height[0];
00135 unsigned nblocksx = pt->nblocksx[0];
00136 unsigned nblocksy = pt->nblocksy[0];
00137
00138 tex->stride = align(pt->nblocksx[0] * pt->block.size, 4);
00139
00140
00141
00142
00143
00144
00145 if (pt->last_level > 0) {
00146 unsigned mip1_nblocksx
00147 = align(pf_get_nblocksx(&pt->block, minify(width)), align_x)
00148 + pf_get_nblocksx(&pt->block, minify(minify(width)));
00149
00150 if (mip1_nblocksx > nblocksx)
00151 tex->stride = mip1_nblocksx * pt->block.size;
00152 }
00153
00154
00155
00156 tex->stride = align(tex->stride, 64);
00157 tex->total_nblocksy = 0;
00158
00159 for (level = 0; level <= pt->last_level; level++) {
00160 intel_miptree_set_level_info(tex, level, 1, x, y, width,
00161 height, 1);
00162
00163 nblocksy = align(nblocksy, align_y);
00164
00165
00166
00167
00168 tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
00169
00170
00171
00172 if (level == 1) {
00173 x += align(nblocksx, align_x);
00174 }
00175 else {
00176 y += nblocksy;
00177 }
00178
00179 width = minify(width);
00180 height = minify(height);
00181 nblocksx = pf_get_nblocksx(&pt->block, width);
00182 nblocksy = pf_get_nblocksy(&pt->block, height);
00183 }
00184 }
00185
00186 static boolean brw_miptree_layout(struct brw_texture *tex)
00187 {
00188 struct pipe_texture *pt = &tex->base;
00189
00190
00191
00192
00193 switch (pt->target) {
00194 case PIPE_TEXTURE_CUBE:
00195 case PIPE_TEXTURE_3D: {
00196 unsigned width = pt->width[0];
00197 unsigned height = pt->height[0];
00198 unsigned depth = pt->depth[0];
00199 unsigned nblocksx = pt->nblocksx[0];
00200 unsigned nblocksy = pt->nblocksy[0];
00201 unsigned pack_x_pitch, pack_x_nr;
00202 unsigned pack_y_pitch;
00203 unsigned level;
00204 unsigned align_h = 2;
00205 unsigned align_w = 4;
00206
00207 tex->total_nblocksy = 0;
00208
00209 tex->stride = align(pt->nblocksx[0], 4);
00210 pack_y_pitch = align(pt->nblocksy[0], align_h);
00211
00212 pack_x_pitch = tex->stride / pt->block.size;
00213 pack_x_nr = 1;
00214
00215 for (level = 0; level <= pt->last_level; level++) {
00216 unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
00217 int x = 0;
00218 int y = 0;
00219 uint q, j;
00220
00221 intel_miptree_set_level_info(tex, level, nr_images,
00222 0, tex->total_nblocksy,
00223 width, height, depth);
00224
00225 for (q = 0; q < nr_images;) {
00226 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
00227 intel_miptree_set_image_offset(tex, level, q, x, y);
00228 x += pack_x_pitch;
00229 }
00230
00231 x = 0;
00232 y += pack_y_pitch;
00233 }
00234
00235
00236 tex->total_nblocksy += y;
00237 width = minify(width);
00238 height = minify(height);
00239 depth = minify(depth);
00240 nblocksx = pf_get_nblocksx(&pt->block, width);
00241 nblocksy = pf_get_nblocksy(&pt->block, height);
00242
00243 if (pt->compressed) {
00244 pack_y_pitch = (height + 3) / 4;
00245
00246 if (pack_x_pitch > align(width, align_w)) {
00247 pack_x_pitch = align(width, align_w);
00248 pack_x_nr <<= 1;
00249 }
00250 } else {
00251 if (pack_x_pitch > 4) {
00252 pack_x_pitch >>= 1;
00253 pack_x_nr <<= 1;
00254 assert(pack_x_pitch * pack_x_nr * pt->block.size <= tex->stride);
00255 }
00256
00257 if (pack_y_pitch > 2) {
00258 pack_y_pitch >>= 1;
00259 pack_y_pitch = align(pack_y_pitch, align_h);
00260 }
00261 }
00262
00263 }
00264 break;
00265 }
00266
00267 default:
00268 i945_miptree_layout_2d(tex);
00269 break;
00270 }
00271 #if 0
00272 PRINT("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
00273 pt->pitch,
00274 pt->total_nblocksy,
00275 pt->block.size,
00276 pt->stride * pt->total_nblocksy );
00277 #endif
00278
00279 return TRUE;
00280 }
00281
00282
00283 static struct pipe_texture *
00284 brw_texture_create_screen(struct pipe_screen *screen,
00285 const struct pipe_texture *templat)
00286 {
00287 struct pipe_winsys *ws = screen->winsys;
00288 struct brw_texture *tex = CALLOC_STRUCT(brw_texture);
00289
00290 if (tex) {
00291 tex->base = *templat;
00292 tex->base.refcount = 1;
00293
00294 tex->base.nblocksx[0] = pf_get_nblocksx(&tex->base.block, tex->base.width[0]);
00295 tex->base.nblocksy[0] = pf_get_nblocksy(&tex->base.block, tex->base.height[0]);
00296
00297 if (brw_miptree_layout(tex))
00298 tex->buffer = ws->buffer_create(ws, 64,
00299 PIPE_BUFFER_USAGE_PIXEL,
00300 tex->stride *
00301 tex->total_nblocksy);
00302
00303 if (!tex->buffer) {
00304 FREE(tex);
00305 return NULL;
00306 }
00307 }
00308
00309 return &tex->base;
00310 }
00311
00312
00313 static void
00314 brw_texture_release_screen(struct pipe_screen *screen,
00315 struct pipe_texture **pt)
00316 {
00317 if (!*pt)
00318 return;
00319
00320
00321
00322
00323
00324 if (--(*pt)->refcount <= 0) {
00325 struct pipe_winsys *ws = screen->winsys;
00326 struct brw_texture *tex = (struct brw_texture *)*pt;
00327 uint i;
00328
00329
00330
00331
00332
00333 winsys_buffer_reference(ws, &tex->buffer, NULL);
00334
00335 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
00336 if (tex->image_offset[i])
00337 free(tex->image_offset[i]);
00338
00339 free(tex);
00340 }
00341 *pt = NULL;
00342 }
00343
00344
00345 static struct pipe_surface *
00346 brw_get_tex_surface_screen(struct pipe_screen *screen,
00347 struct pipe_texture *pt,
00348 unsigned face, unsigned level, unsigned zslice)
00349 {
00350 struct pipe_winsys *ws = screen->winsys;
00351 struct brw_texture *tex = (struct brw_texture *)pt;
00352 struct pipe_surface *ps;
00353 unsigned offset;
00354
00355 offset = tex->level_offset[level];
00356
00357 if (pt->target == PIPE_TEXTURE_CUBE) {
00358 offset += tex->image_offset[level][face];
00359 }
00360 else if (pt->target == PIPE_TEXTURE_3D) {
00361 offset += tex->image_offset[level][zslice];
00362 }
00363 else {
00364 assert(face == 0);
00365 assert(zslice == 0);
00366 }
00367
00368 ps = ws->surface_alloc(ws);
00369 if (ps) {
00370 assert(ps->format);
00371 assert(ps->refcount);
00372 winsys_buffer_reference(ws, &ps->buffer, tex->buffer);
00373 ps->format = pt->format;
00374 ps->width = pt->width[level];
00375 ps->height = pt->height[level];
00376 ps->block = pt->block;
00377 ps->nblocksx = pt->nblocksx[level];
00378 ps->nblocksy = pt->nblocksy[level];
00379 ps->stride = tex->stride;
00380 ps->offset = offset;
00381 }
00382 return ps;
00383 }
00384
00385
00386 void
00387 brw_init_texture_functions(struct brw_context *brw)
00388 {
00389
00390 }
00391
00392
00393 void
00394 brw_init_screen_texture_funcs(struct pipe_screen *screen)
00395 {
00396 screen->texture_create = brw_texture_create_screen;
00397 screen->texture_release = brw_texture_release_screen;
00398 screen->get_tex_surface = brw_get_tex_surface_screen;
00399 }
00400