#define CELL_CMD_STATE_FRAMEBUFFER 10
#define CELL_CMD_STATE_DEPTH_STENCIL 11
#define CELL_CMD_STATE_SAMPLER 12
-#define CELL_CMD_STATE_VERTEX_INFO 13
+#define CELL_CMD_STATE_TEXTURE 13
+#define CELL_CMD_STATE_VERTEX_INFO 14
#define CELL_NUM_BUFFERS 4
};
+struct cell_command_texture
+{
+ void *start; /**< Address in main memory */
+ uint width, height;
+};
+
+
/** XXX unions don't seem to work */
struct cell_command
{
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
- struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
+ struct cell_texture *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
ubyte *zsbuf_map;
+ struct pipe_surface *tex_surf;
+ uint *tex_map;
+
uint dirty;
/** The primitive drawing context */
#include "cell_state.h"
#include "cell_state_emit.h"
#include "cell_batch.h"
-
+#include "cell_texture.h"
static void
cell->sampler[0], sizeof(struct pipe_sampler_state));
}
+ if (cell->dirty & CELL_NEW_TEXTURE) {
+ struct cell_command_texture texture;
+ texture.start = cell->texture[0]->tiled_data;
+ texture.width = cell->texture[0]->base.width[0];
+ texture.height = cell->texture[0]->base.height[0];
+
+ emit_state_cmd(cell, CELL_CMD_STATE_TEXTURE,
+ &texture, sizeof(struct cell_command_texture));
+ }
+
if (cell->dirty & CELL_NEW_VERTEX_INFO) {
emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
&cell->vertex_info, sizeof(struct vertex_info));
*/
#include "pipe/p_util.h"
+#include "pipe/draw/draw_context.h"
#include "cell_context.h"
#include "cell_state.h"
-#if 0
#include "cell_texture.h"
-#include "cell_tile_cache.h"
-#endif
void *
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
assert(unit < PIPE_MAX_SAMPLERS);
cell->sampler[unit] = (struct pipe_sampler_state *)sampler;
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
cell->texture[sampler] = texture;
+ cell_update_texture_mapping(cell);
+
cell->dirty |= CELL_NEW_TEXTURE;
}
}
return ps;
}
+
+
+
+static void
+tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
+{
+ const uint tile_size2 = tile_size * tile_size;
+ const uint h_t = h / tile_size, w_t = w / tile_size;
+
+ uint it, jt; /* tile counters */
+ uint i, j; /* intra-tile counters */
+
+ for (it = 0; it < h_t; it++) {
+ for (jt = 0; jt < w_t; jt++) {
+ /* fill in tile (i, j) */
+ uint *tdst = dst + (it * w_t + jt) * tile_size2;
+ for (i = 0; i < tile_size; i++) {
+ for (j = 0; j < tile_size; j++) {
+ const uint srci = it * tile_size + i;
+ const uint srcj = jt * tile_size + j;
+ *tdst++ = src[srci * h + srcj];
+ }
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Convert linear texture image data to tiled format for SPU usage.
+ */
+static void
+cell_tile_texture(struct cell_context *cell,
+ struct cell_texture *texture)
+{
+ uint face = 0, level = 0, zslice = 0;
+ struct pipe_surface *surf;
+ const uint w = texture->base.width[0], h = texture->base.height[0];
+ const uint *src;
+
+ /* temporary restrictions: */
+ assert(w >= TILE_SIZE);
+ assert(h >= TILE_SIZE);
+ assert(w % TILE_SIZE == 0);
+ assert(h % TILE_SIZE == 0);
+
+ surf = cell_get_tex_surface(&cell->pipe, &texture->base, face, level, zslice);
+ ASSERT(surf);
+
+ src = (const uint *) pipe_surface_map(surf);
+
+ if (texture->tiled_data) {
+ align_free(texture->tiled_data);
+ }
+ texture->tiled_data = align_malloc(w * h * 4, 16);
+
+ tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src);
+
+ pipe_surface_unmap(surf);
+
+ pipe_surface_reference(&surf, NULL);
+}
+
+
+
+void
+cell_update_texture_mapping(struct cell_context *cell)
+{
+ uint face = 0, level = 0, zslice = 0;
+
+ cell_tile_texture(cell, cell->texture[0]);
+#if 0
+ if (cell->tex_surf && cell->tex_map) {
+ pipe_surface_unmap(cell->tex_surf);
+ cell->tex_map = NULL;
+ }
+
+ /* XXX free old surface */
+
+ cell->tex_surf = cell_get_tex_surface(&cell->pipe,
+ &cell->texture[0]->base,
+ face, level, zslice);
+
+ cell->tex_map = pipe_surface_map(cell->tex_surf);
+#endif
+}
*/
struct pipe_buffer *buffer;
unsigned long buffer_size;
+
+ void *tiled_data; /* XXX this may be temporary */ /*ALIGN16*/
};
unsigned face, unsigned level, unsigned zslice);
+extern void
+cell_update_texture_mapping(struct cell_context *cell);
+
+
#endif /* CELL_TEXTURE */
SOURCES = \
spu_main.c \
+ spu_texture.c \
spu_tile.c \
spu_tri.c
#include <spu_mfcio.h>
#include "spu_main.h"
+#include "spu_texture.h"
#include "spu_tri.h"
#include "spu_tile.h"
#include "pipe/cell/common.h"
}
+static void
+cmd_state_texture(const struct cell_command_texture *texture)
+{
+ if (Debug)
+ printf("SPU %u: TEXTURE at %p size %u x %u\n",
+ spu.init.id, texture->start, texture->width, texture->height);
+
+ memcpy(&spu.texture, texture, sizeof(*texture));
+}
+
+
static void
cmd_state_vertex_info(const struct vertex_info *vinfo)
{
cmd_state_sampler((struct pipe_sampler_state *) &buffer[pos+1]);
pos += (1 + sizeof(struct pipe_sampler_state) / 4);
break;
+ case CELL_CMD_STATE_TEXTURE:
+ cmd_state_texture((struct cell_command_texture *) &buffer[pos+1]);
+ pos += (1 + sizeof(struct cell_command_texture) / 4);
+ break;
case CELL_CMD_STATE_VERTEX_INFO:
cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]);
pos += (1 + sizeof(struct vertex_info) / 4);
{
memset(tile_status, TILE_STATUS_DEFINED, sizeof(tile_status));
memset(tile_status_z, TILE_STATUS_DEFINED, sizeof(tile_status_z));
+ invalidate_tex_cache();
}
struct pipe_depth_stencil_alpha_state depth_stencil;
struct pipe_blend_state blend;
struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
+ struct cell_command_texture texture;
struct vertex_info vertex_info;
#define TAG_INDEX_BUFFER 16
#define TAG_BATCH_BUFFER 17
#define TAG_MISC 18
+#define TAG_TEXTURE_TILE 19
+
extern void
#include "pipe/p_format.h"
#include "pipe/p_util.h"
#include "spu_main.h"
+#include "spu_texture.h"
#include "spu_tile.h"
#include "spu_tri.h"
/* Cell: "write" quad fragments to the tile by setting prim color */
const int ix = x - setup->cliprect_minx;
const int iy = y - setup->cliprect_miny;
- float colors[4][4];
-
- eval_coeff(setup, 1, (float) x, (float) y, colors);
+ uint colors[4]; /* indexed by QUAD_x */
+
+ if (spu.texture.start) {
+ float texcoords[4][4];
+ uint i;
+ eval_coeff(setup, 2, (float) x, (float) y, texcoords);
+ for (i = 0; i < 4; i++) {
+ colors[i] = sample_texture(texcoords[i]);
+ }
+ }
+ else {
+ float fcolors[4][4];
+ eval_coeff(setup, 1, (float) x, (float) y, fcolors);
+ colors[QUAD_TOP_LEFT] = pack_color(fcolors[QUAD_TOP_LEFT]);
+ colors[QUAD_TOP_RIGHT] = pack_color(fcolors[QUAD_TOP_RIGHT]);
+ colors[QUAD_BOTTOM_LEFT] = pack_color(fcolors[QUAD_BOTTOM_LEFT]);
+ colors[QUAD_BOTTOM_RIGHT] = pack_color(fcolors[QUAD_BOTTOM_RIGHT]);
+ }
if (spu.depth_stencil.depth.enabled) {
mask &= do_depth_test(setup, x, y, mask);
tile_status[setup->ty][setup->tx] = TILE_STATUS_DIRTY;
if (mask & MASK_TOP_LEFT)
- ctile.t32[iy][ix] = pack_color(colors[QUAD_TOP_LEFT]);
+ ctile.t32[iy][ix] = colors[QUAD_TOP_LEFT];
if (mask & MASK_TOP_RIGHT)
- ctile.t32[iy][ix+1] = pack_color(colors[QUAD_TOP_RIGHT]);
+ ctile.t32[iy][ix+1] = colors[QUAD_TOP_RIGHT];
if (mask & MASK_BOTTOM_LEFT)
- ctile.t32[iy+1][ix] = pack_color(colors[QUAD_BOTTOM_LEFT]);
+ ctile.t32[iy+1][ix] = colors[QUAD_BOTTOM_LEFT];
if (mask & MASK_BOTTOM_RIGHT)
- ctile.t32[iy+1][ix+1] = pack_color(colors[QUAD_BOTTOM_RIGHT]);
+ ctile.t32[iy+1][ix+1] = colors[QUAD_BOTTOM_RIGHT];
}
#endif
}
}
-#if 0
/**
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
* The value value comes from vertex->data[slot][i].
* \param slot which attribute slot
* \param i which component of the slot (0..3)
*/
-static void const_coeff( struct setup_stage *setup,
- unsigned slot,
- unsigned i )
+static void const_coeff(struct setup_stage *setup, uint slot)
{
- assert(slot < PIPE_MAX_SHADER_INPUTS);
- assert(i <= 3);
+ uint i;
+ ASSERT(slot < PIPE_MAX_SHADER_INPUTS);
- setup->coef[slot].dadx[i] = 0;
- setup->coef[slot].dady[i] = 0;
+ for (i = 0; i < 4; i++) {
+ setup->coef[slot].dadx[i] = 0;
+ setup->coef[slot].dady[i] = 0;
- /* need provoking vertex info!
- */
- setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i];
+ /* need provoking vertex info!
+ */
+ setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i];
+ }
}
-#endif
/**
case INTERP_NONE:
break;
case INTERP_POS:
- tri_linear_coeff(setup, i, 2, 3); /* slot 0, z */
+ tri_linear_coeff(setup, i, 2, 3);
/* XXX interp W if PERSPECTIVE... */
break;
case INTERP_CONSTANT:
- /* fall-through */
+ const_coeff(setup, i);
+ break;
case INTERP_LINEAR:
- tri_linear_coeff(setup, i, 0, 4); /* slot 1, color */
+ tri_linear_coeff(setup, i, 0, 4);
break;
case INTERP_PERSPECTIVE:
+ tri_linear_coeff(setup, i, 0, 4); /* XXX temporary */
break;
default:
ASSERT(0);