mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 00:00:11 +01:00
Cell: basic texture mapping
Texture images are tiled in PPU code. SPUs use a texture cache for getting texels from textures. This is very rough code, but demos/texcyl.c works.
This commit is contained in:
parent
c2372cc748
commit
425f270fcb
10 changed files with 182 additions and 27 deletions
|
|
@ -79,7 +79,8 @@
|
|||
#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
|
||||
|
|
@ -134,6 +135,13 @@ struct cell_command_release_verts
|
|||
};
|
||||
|
||||
|
||||
struct cell_command_texture
|
||||
{
|
||||
void *start; /**< Address in main memory */
|
||||
uint width, height;
|
||||
};
|
||||
|
||||
|
||||
/** XXX unions don't seem to work */
|
||||
struct cell_command
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ struct cell_context
|
|||
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];
|
||||
|
|
@ -84,6 +84,9 @@ struct cell_context
|
|||
ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
|
||||
ubyte *zsbuf_map;
|
||||
|
||||
struct pipe_surface *tex_surf;
|
||||
uint *tex_map;
|
||||
|
||||
uint dirty;
|
||||
|
||||
/** The primitive drawing context */
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "cell_state.h"
|
||||
#include "cell_state_emit.h"
|
||||
#include "cell_batch.h"
|
||||
|
||||
#include "cell_texture.h"
|
||||
|
||||
|
||||
static void
|
||||
|
|
@ -72,6 +72,16 @@ cell_emit_state(struct cell_context *cell)
|
|||
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));
|
||||
|
|
|
|||
|
|
@ -30,12 +30,10 @@
|
|||
*/
|
||||
|
||||
#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 *
|
||||
|
|
@ -53,6 +51,8 @@ cell_bind_sampler_state(struct pipe_context *pipe,
|
|||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
assert(unit < PIPE_MAX_SAMPLERS);
|
||||
cell->sampler[unit] = (struct pipe_sampler_state *)sampler;
|
||||
|
||||
|
|
@ -76,7 +76,11 @@ cell_set_sampler_texture(struct pipe_context *pipe,
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,3 +163,90 @@ cell_get_tex_surface(struct pipe_context *pipe,
|
|||
}
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ struct cell_texture
|
|||
*/
|
||||
struct pipe_buffer *buffer;
|
||||
unsigned long buffer_size;
|
||||
|
||||
void *tiled_data; /* XXX this may be temporary */ /*ALIGN16*/
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -70,4 +72,8 @@ cell_get_tex_surface(struct pipe_context *pipe,
|
|||
unsigned face, unsigned level, unsigned zslice);
|
||||
|
||||
|
||||
extern void
|
||||
cell_update_texture_mapping(struct cell_context *cell);
|
||||
|
||||
|
||||
#endif /* CELL_TEXTURE */
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ PROG_SPU_EMBED_O = $(PROG)_spu-embed.o
|
|||
|
||||
SOURCES = \
|
||||
spu_main.c \
|
||||
spu_texture.c \
|
||||
spu_tile.c \
|
||||
spu_tri.c
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#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"
|
||||
|
|
@ -446,6 +447,17 @@ cmd_state_sampler(const struct pipe_sampler_state *state)
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -561,6 +573,10 @@ cmd_batch(uint opcode)
|
|||
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);
|
||||
|
|
@ -656,6 +672,7 @@ one_time_init(void)
|
|||
{
|
||||
memset(tile_status, TILE_STATUS_DEFINED, sizeof(tile_status));
|
||||
memset(tile_status_z, TILE_STATUS_DEFINED, sizeof(tile_status_z));
|
||||
invalidate_tex_cache();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ struct spu_global
|
|||
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;
|
||||
|
||||
|
|
@ -84,6 +85,8 @@ extern struct spu_global spu;
|
|||
#define TAG_INDEX_BUFFER 16
|
||||
#define TAG_BATCH_BUFFER 17
|
||||
#define TAG_MISC 18
|
||||
#define TAG_TEXTURE_TILE 19
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -362,9 +363,24 @@ emit_quad( struct setup_stage *setup, int x, int y, unsigned mask )
|
|||
/* 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];
|
||||
uint colors[4]; /* indexed by QUAD_x */
|
||||
|
||||
eval_coeff(setup, 1, (float) x, (float) y, colors);
|
||||
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);
|
||||
|
|
@ -382,13 +398,13 @@ emit_quad( struct setup_stage *setup, int x, int y, unsigned 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
|
||||
}
|
||||
|
|
@ -606,7 +622,6 @@ static boolean setup_sort_vertices( struct setup_stage *setup,
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
|
||||
* The value value comes from vertex->data[slot][i].
|
||||
|
|
@ -614,21 +629,20 @@ static boolean setup_sort_vertices( struct setup_stage *setup,
|
|||
* \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
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -735,15 +749,17 @@ static void setup_tri_coefficients( struct setup_stage *setup )
|
|||
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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue