diff options
Diffstat (limited to 'src/gallium/drivers/cell')
20 files changed, 483 insertions, 165 deletions
diff --git a/src/gallium/drivers/cell/ppu/Makefile b/src/gallium/drivers/cell/ppu/Makefile index c92f8e5cba..8769b826b5 100644 --- a/src/gallium/drivers/cell/ppu/Makefile +++ b/src/gallium/drivers/cell/ppu/Makefile @@ -21,6 +21,7 @@ SPU_CODE_MODULE = ../spu/g3d_spu.a SOURCES = \ cell_batch.c \ + cell_buffer.c \ cell_clear.c \ cell_context.c \ cell_draw_arrays.c \ diff --git a/src/gallium/drivers/cell/ppu/cell_buffer.c b/src/gallium/drivers/cell/ppu/cell_buffer.c new file mode 100644 index 0000000000..f56a28d62e --- /dev/null +++ b/src/gallium/drivers/cell/ppu/cell_buffer.c @@ -0,0 +1,118 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "cell_screen.h" +#include "cell_buffer.h" + + +static void * +cell_buffer_map(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned flags) +{ + struct cell_buffer *cell_buf = cell_buffer(buf); + return cell_buf->data; +} + + +static void +cell_buffer_unmap(struct pipe_screen *screen, + struct pipe_buffer *buf) +{ +} + + +static void +cell_buffer_destroy(struct pipe_buffer *buf) +{ + struct cell_buffer *sbuf = cell_buffer(buf); + + if (!sbuf->userBuffer) + align_free(sbuf->data); + + FREE(sbuf); +} + + +static struct pipe_buffer * +cell_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct cell_buffer *buffer = CALLOC_STRUCT(cell_buffer); + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.alignment = MAX2(alignment, 16); + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +cell_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes) +{ + struct cell_buffer *buffer; + + buffer = CALLOC_STRUCT(cell_buffer); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +void +cell_init_screen_buffer_funcs(struct pipe_screen *screen) +{ + screen->buffer_create = cell_buffer_create; + screen->user_buffer_create = cell_user_buffer_create; + screen->buffer_map = cell_buffer_map; + screen->buffer_unmap = cell_buffer_unmap; + screen->buffer_destroy = cell_buffer_destroy; +} diff --git a/src/gallium/drivers/cell/ppu/cell_winsys.h b/src/gallium/drivers/cell/ppu/cell_buffer.h index e227e065ff..ef0a8a70e5 100644 --- a/src/gallium/drivers/cell/ppu/cell_winsys.h +++ b/src/gallium/drivers/cell/ppu/cell_buffer.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2009 VMware, Inc. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,38 +10,46 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * + * **************************************************************************/ - -#ifndef CELL_WINSYS_H -#define CELL_WINSYS_H +#ifndef SP_BUFFER_H +#define SP_BUFFER_H #include "pipe/p_compiler.h" +#include "pipe/p_state.h" -/** - * Very simple winsys at this time. - * Will probably eventually add SPU control info. - */ -struct cell_winsys +struct cell_buffer { - uint dummy; + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; }; +/** Cast wrapper */ +static INLINE struct cell_buffer * +cell_buffer( struct pipe_buffer *buf ) +{ + return (struct cell_buffer *)buf; +} + + +void +cell_init_screen_buffer_funcs(struct pipe_screen *screen); -#endif +#endif /* SP_BUFFER_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index 5bff9869fd..f6cb1fc9be 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -36,7 +36,6 @@ #include "pipe/p_defines.h" #include "pipe/p_format.h" #include "util/u_memory.h" -#include "util/u_simple_screen.h" #include "pipe/p_screen.h" #include "draw/draw_context.h" @@ -137,7 +136,7 @@ cell_create_context(struct pipe_screen *screen, memset(cell, 0, sizeof(*cell)); cell->winsys = NULL; /* XXX: fixme - get this from screen? */ - cell->pipe.winsys = screen->winsys; + cell->pipe.winsys = NULL; cell->pipe.screen = screen; cell->pipe.priv = priv; cell->pipe.destroy = cell_destroy_context; @@ -159,6 +158,7 @@ cell_create_context(struct pipe_screen *screen, cell_init_shader_functions(cell); cell_init_surface_functions(cell); cell_init_vertex_functions(cell); + cell_init_texture_transfer_funcs(cell); cell->draw = cell_draw_create(cell); diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index a77cc5b906..f7e2284445 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -34,7 +34,7 @@ #include "pipe/p_defines.h" #include "draw/draw_vertex.h" #include "draw/draw_vbuf.h" -#include "cell_winsys.h" +/*#include "cell_winsys.h"*/ #include "cell/common.h" #include "rtasm/rtasm_ppc_spe.h" #include "tgsi/tgsi_scan.h" @@ -93,6 +93,11 @@ struct cell_buffer_list struct cell_buffer_node *head; }; +struct cell_velems_state +{ + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; /** * Per-context state, subclass of pipe_context. @@ -110,6 +115,7 @@ struct cell_context const struct pipe_rasterizer_state *rasterizer; const struct cell_vertex_shader_state *vs; const struct cell_fragment_shader_state *fs; + const struct cell_velems_state *velems; struct spe_function logic_op; @@ -121,12 +127,11 @@ struct cell_context struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; struct cell_texture *texture[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; uint num_textures; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; uint num_vertex_buffers; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; - uint num_vertex_elements; ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS]; ubyte *zsbuf_map; diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index bffd0fac6f..15d4e8338f 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -33,48 +33,18 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" #include "cell_context.h" #include "cell_draw_arrays.h" #include "cell_state.h" #include "cell_flush.h" +#include "cell_buffer.h" #include "draw/draw_context.h" -static void -cell_map_constant_buffers(struct cell_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - for (i = 0; i < 2; i++) { - if (sp->constants[i] && sp->constants[i]->size) { - sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i], - PIPE_BUFFER_USAGE_CPU_READ); - cell_flush_buffer_range(sp, sp->mapped_constants[i], - sp->constants[i]->size); - } - } - - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, 0, - sp->mapped_constants[PIPE_SHADER_VERTEX], - sp->constants[PIPE_SHADER_VERTEX]->size); -} - -static void -cell_unmap_constant_buffers(struct cell_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - for (i = 0; i < 2; i++) { - if (sp->constants[i] && sp->constants[i]->size) - ws->buffer_unmap(ws, sp->constants[i]); - sp->mapped_constants[i] = NULL; - } -} @@ -93,33 +63,27 @@ cell_draw_range_elements(struct pipe_context *pipe, unsigned max_index, unsigned mode, unsigned start, unsigned count) { - struct cell_context *sp = cell_context(pipe); - struct draw_context *draw = sp->draw; + struct cell_context *cell = cell_context(pipe); + struct draw_context *draw = cell->draw; unsigned i; - if (sp->dirty) - cell_update_derived( sp ); + if (cell->dirty) + cell_update_derived( cell ); #if 0 - cell_map_surfaces(sp); + cell_map_surfaces(cell); #endif - cell_map_constant_buffers(sp); /* * Map vertex buffers */ - for (i = 0; i < sp->num_vertex_buffers; i++) { - void *buf = pipe_buffer_map(pipe->screen, - sp->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); - cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size); + for (i = 0; i < cell->num_vertex_buffers; i++) { + void *buf = cell_buffer(cell->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { - void *mapped_indexes = pipe_buffer_map(pipe->screen, - indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *mapped_indexes = cell_buffer(indexBuffer)->data; draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { @@ -134,17 +98,19 @@ cell_draw_range_elements(struct pipe_context *pipe, /* * unmap vertex/index buffers - will cause draw module to flush */ - for (i = 0; i < sp->num_vertex_buffers; i++) { + for (i = 0; i < cell->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); - pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); } if (indexBuffer) { draw_set_mapped_element_buffer(draw, 0, NULL); - pipe_buffer_unmap(pipe->screen, indexBuffer); } - /* Note: leave drawing surfaces mapped */ - cell_unmap_constant_buffers(sp); + /* + * TODO: Flush only when a user vertex/index buffer is present + * (or even better, modify draw module to do this + * internally when this condition is seen?) + */ + draw_flush(draw); } diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c index e10071529a..035ef41b89 100644 --- a/src/gallium/drivers/cell/ppu/cell_fence.c +++ b/src/gallium/drivers/cell/ppu/cell_fence.c @@ -92,7 +92,6 @@ cell_add_buffer_to_list(struct cell_context *cell, struct cell_buffer_list *list, struct pipe_buffer *buffer) { - struct pipe_screen *ps = cell->pipe.screen; struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node); /* create new list node which references the buffer, insert at head */ if (node) { @@ -157,8 +156,13 @@ cell_add_fenced_textures(struct cell_context *cell) printf("Adding texture %p buffer %p to list\n", ct, ct->tiled_buffer[level]); #endif - if (ct->buffer) +#if 00 + /* XXX this needs to be fixed/restored! + * Maybe keep pointers to textures, not buffers. + */ + if (ct->base.buffer) cell_add_buffer_to_list(cell, list, ct->buffer); +#endif } } } diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index c54576b3c3..628bc1c694 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -1859,7 +1859,7 @@ gen_depth_stencil(struct cell_context *cell, spe_comment(f, 0, "Fetch Z/stencil quad from tile"); switch(zs_format) { - case PIPE_FORMAT_Z24S8_UNORM: /* fall through */ + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: /* fall through */ case PIPE_FORMAT_Z24X8_UNORM: /* prepare mask to extract Z vals from ZS vals */ spe_load_uint(f, zmask_reg, 0x00ffffff); @@ -1880,7 +1880,7 @@ gen_depth_stencil(struct cell_context *cell, spe_rotmi(f, fbS_reg, fbZS_reg, -24); break; - case PIPE_FORMAT_S8Z24_UNORM: /* fall through */ + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: /* fall through */ case PIPE_FORMAT_X8Z24_UNORM: /* convert fragment Z from [0,1] to 32-bit ints */ spe_cfltu(f, fragZ_reg, fragZ_reg, 32); @@ -1969,12 +1969,12 @@ gen_depth_stencil(struct cell_context *cell, * fbS_reg has four 8-bit Z values in bits [7..0]. */ spe_comment(f, 0, "Store quad's depth/stencil values in tile"); - if (zs_format == PIPE_FORMAT_Z24S8_UNORM || + if (zs_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || zs_format == PIPE_FORMAT_Z24X8_UNORM) { spe_shli(f, fbS_reg, fbS_reg, 24); /* fbS = fbS << 24 */ spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */ } - else if (zs_format == PIPE_FORMAT_S8Z24_UNORM || + else if (zs_format == PIPE_FORMAT_S8_USCALED_Z24_UNORM || zs_format == PIPE_FORMAT_X8Z24_UNORM) { spe_shli(f, fbZ_reg, fbZ_reg, 8); /* fbZ = fbZ << 8 */ spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */ @@ -1985,7 +1985,7 @@ gen_depth_stencil(struct cell_context *cell, else if (zs_format == PIPE_FORMAT_Z16_UNORM) { spe_move(f, fbZS_reg, fbZ_reg); /* fbZS = fbZ */ } - else if (zs_format == PIPE_FORMAT_S8_UNORM) { + else if (zs_format == PIPE_FORMAT_S8_USCALED) { ASSERT(0); /* XXX to do */ } else { @@ -2015,7 +2015,7 @@ gen_depth_stencil(struct cell_context *cell, * code before the fragment shader to cull fragments/quads that are * totally occluded/discarded. * - * XXX we only support PIPE_FORMAT_S8Z24_UNORM z/stencil buffer right now. + * XXX we only support PIPE_FORMAT_S8_USCALED_Z24_UNORM z/stencil buffer right now. * * See the spu_default_fragment_ops() function to see how the per-fragment * operations would be done with ordinary C code. diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index 3d8b4409c7..059ce8597b 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -257,8 +257,9 @@ cell_delete_sampler_state(struct pipe_context *pipe, static void -cell_set_sampler_textures(struct pipe_context *pipe, - unsigned num, struct pipe_texture **texture) +cell_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) { struct cell_context *cell = cell_context(pipe); uint i, changed = 0x0; @@ -266,10 +267,14 @@ cell_set_sampler_textures(struct pipe_context *pipe, assert(num <= CELL_MAX_SAMPLERS); for (i = 0; i < CELL_MAX_SAMPLERS; i++) { - struct cell_texture *new_tex = cell_texture(i < num ? texture[i] : NULL); - struct cell_texture *old_tex = cell->texture[i]; - if (old_tex != new_tex) { + struct pipe_sampler_view *new_view = i < num ? views[i] : NULL; + struct pipe_sampler_view *old_view = cell->fragment_sampler_views[i]; + if (old_view != new_view) { + struct pipe_texture *new_tex = new_view ? new_view->texture : NULL; + + pipe_sampler_view_reference(&cell->fragment_sampler_views[i], + views[i]); pipe_texture_reference((struct pipe_texture **) &cell->texture[i], (struct pipe_texture *) new_tex); @@ -286,23 +291,57 @@ cell_set_sampler_textures(struct pipe_context *pipe, } +static struct pipe_sampler_view * +cell_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +cell_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + + /** * Map color and z/stencil framebuffer surfaces. */ static void cell_map_surfaces(struct cell_context *cell) { +#if 0 struct pipe_screen *screen = cell->pipe.screen; +#endif uint i; for (i = 0; i < 1; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps) { struct cell_texture *ct = cell_texture(ps->texture); +#if 0 cell->cbuf_map[i] = screen->buffer_map(screen, ct->buffer, (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE)); +#else + cell->cbuf_map[i] = ct->data; +#endif } } @@ -310,10 +349,14 @@ cell_map_surfaces(struct cell_context *cell) struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps) { struct cell_texture *ct = cell_texture(ps->texture); +#if 0 cell->zsbuf_map = screen->buffer_map(screen, ct->buffer, (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE)); +#else + cell->zsbuf_map = ct->data; +#endif } } } @@ -325,17 +368,17 @@ cell_map_surfaces(struct cell_context *cell) static void cell_unmap_surfaces(struct cell_context *cell) { - struct pipe_screen *screen = cell->pipe.screen; + /*struct pipe_screen *screen = cell->pipe.screen;*/ uint i; for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps && cell->cbuf_map[i]) { - struct cell_texture *ct = cell_texture(ps->texture); + /*struct cell_texture *ct = cell_texture(ps->texture);*/ assert(ps->texture); - assert(ct->buffer); + /*assert(ct->buffer);*/ - screen->buffer_unmap(screen, ct->buffer); + /*screen->buffer_unmap(screen, ct->buffer);*/ cell->cbuf_map[i] = NULL; } } @@ -343,8 +386,8 @@ cell_unmap_surfaces(struct cell_context *cell) { struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps && cell->zsbuf_map) { - struct cell_texture *ct = cell_texture(ps->texture); - screen->buffer_unmap(screen, ct->buffer); + /*struct cell_texture *ct = cell_texture(ps->texture);*/ + /*screen->buffer_unmap(screen, ct->buffer);*/ cell->zsbuf_map = NULL; } } @@ -399,7 +442,9 @@ cell_init_state_functions(struct cell_context *cell) cell->pipe.bind_fragment_sampler_states = cell_bind_sampler_states; cell->pipe.delete_sampler_state = cell_delete_sampler_state; - cell->pipe.set_fragment_sampler_textures = cell_set_sampler_textures; + cell->pipe.set_fragment_sampler_views = cell_set_fragment_sampler_views; + cell->pipe.create_sampler_view = cell_create_sampler_view; + cell->pipe.sampler_view_destroy = cell_sampler_view_destroy; cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state; cell->pipe.bind_depth_stencil_alpha_state = cell_bind_depth_stencil_alpha_state; diff --git a/src/gallium/drivers/cell/ppu/cell_public.h b/src/gallium/drivers/cell/ppu/cell_public.h new file mode 100644 index 0000000000..7e2e093565 --- /dev/null +++ b/src/gallium/drivers/cell/ppu/cell_public.h @@ -0,0 +1,10 @@ +#ifndef CELL_PUBLIC_H +#define CELL_PUBLIC_H + +struct pipe_screen; +struct sw_winsys; + +struct pipe_screen * +cell_create_screen(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index 7957e0149d..363d1e65e7 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -28,7 +28,6 @@ #include "util/u_memory.h" #include "util/u_simple_screen.h" -#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -36,7 +35,10 @@ #include "cell_context.h" #include "cell_screen.h" #include "cell_texture.h" -#include "cell_winsys.h" +#include "cell_buffer.h" +#include "cell_public.h" + +#include "state_tracker/sw_winsys.h" static const char * @@ -136,9 +138,16 @@ cell_is_format_supported( struct pipe_screen *screen, unsigned tex_usage, unsigned geom_flags ) { + if (tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) + return FALSE; + } + /* only a few formats are known to work at this time */ switch (format) { - case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_I8_UNORM: @@ -152,7 +161,8 @@ cell_is_format_supported( struct pipe_screen *screen, static void cell_destroy_screen( struct pipe_screen *screen ) { - struct pipe_winsys *winsys = screen->winsys; + struct cell_screen *sp_screen = cell_screen(screen); + struct sw_winsys *winsys = sp_screen->winsys; if(winsys->destroy) winsys->destroy(winsys); @@ -161,32 +171,34 @@ cell_destroy_screen( struct pipe_screen *screen ) } + /** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no cell_screen) but * that would be the place to put SPU thread/context info... */ struct pipe_screen * -cell_create_screen(struct pipe_winsys *winsys) +cell_create_screen(struct sw_winsys *winsys) { - struct pipe_screen *screen = CALLOC_STRUCT(pipe_screen); + struct cell_screen *screen = CALLOC_STRUCT(cell_screen); if (!screen) return NULL; screen->winsys = winsys; + screen->base.winsys = NULL; - screen->destroy = cell_destroy_screen; + screen->base.destroy = cell_destroy_screen; - screen->get_name = cell_get_name; - screen->get_vendor = cell_get_vendor; - screen->get_param = cell_get_param; - screen->get_paramf = cell_get_paramf; - screen->is_format_supported = cell_is_format_supported; - screen->context_create = cell_create_context; + screen->base.get_name = cell_get_name; + screen->base.get_vendor = cell_get_vendor; + screen->base.get_param = cell_get_param; + screen->base.get_paramf = cell_get_paramf; + screen->base.is_format_supported = cell_is_format_supported; + screen->base.context_create = cell_create_context; - cell_init_screen_texture_funcs(screen); - u_simple_screen_init(screen); + cell_init_screen_texture_funcs(&screen->base); + cell_init_screen_buffer_funcs(&screen->base); - return screen; + return &screen->base; } diff --git a/src/gallium/drivers/cell/ppu/cell_screen.h b/src/gallium/drivers/cell/ppu/cell_screen.h index c7e15889d6..baff9d3b7d 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.h +++ b/src/gallium/drivers/cell/ppu/cell_screen.h @@ -30,12 +30,26 @@ #define CELL_SCREEN_H -struct pipe_screen; -struct pipe_winsys; +#include "pipe/p_screen.h" +struct sw_winsys; -extern struct pipe_screen * -cell_create_screen(struct pipe_winsys *winsys); +struct cell_screen { + struct pipe_screen base; + + struct sw_winsys *winsys; + + /* Increments whenever textures are modified. Contexts can track + * this. + */ + unsigned timestamp; +}; + +static INLINE struct cell_screen * +cell_screen( struct pipe_screen *pipe ) +{ + return (struct cell_screen *)pipe; +} #endif /* CELL_SCREEN_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index a59c7828ac..424e2628a9 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -245,16 +245,13 @@ cell_emit_state(struct cell_context *cell) uint i, j; float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float))); uint32_t *ibuf = (uint32_t *) buf; - const float *constants = pipe_buffer_map(cell->pipe.screen, - cell->constants[shader], - PIPE_BUFFER_USAGE_CPU_READ); + const float *constants = cell->mapped_constants[shader]; ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS; ibuf[4] = num_const; j = 8; for (i = 0; i < num_const; i++) { buf[j++] = constants[i]; } - pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader]); } if (cell->dirty & (CELL_NEW_FRAMEBUFFER | diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c index 9b2f86fdfb..9e29ddc2d4 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c @@ -28,13 +28,13 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" #include "util/u_inlines.h" -#include "util/u_simple_screen.h" #include "draw/draw_context.h" #include "tgsi/tgsi_parse.h" #include "cell_context.h" #include "cell_state.h" #include "cell_gen_fp.h" +#include "cell_buffer.h" /** cast wrapper */ @@ -183,17 +183,29 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs) static void cell_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_buffer *constants) { struct cell_context *cell = cell_context(pipe); + unsigned size = constants ? constants->size : 0; + const void *data = constants ? cell_buffer(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); + if (cell->constants[shader] == constants) + return; + draw_flush(cell->draw); /* note: reference counting */ - pipe_buffer_reference(&cell->constants[shader], buf); + pipe_buffer_reference(&cell->constants[shader], constants); + + if(shader == PIPE_SHADER_VERTEX) { + draw_set_mapped_constant_buffer(cell->draw, PIPE_SHADER_VERTEX, 0, + data, size); + } + + cell->mapped_constants[shader] = data; if (shader == PIPE_SHADER_VERTEX) cell->dirty |= CELL_NEW_VS_CONSTANTS; diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c index fbe55c8472..9510ea9ac2 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c +++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c @@ -32,24 +32,44 @@ #include "cell_context.h" #include "cell_state.h" +#include "util/u_memory.h" #include "draw/draw_context.h" -static void -cell_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements) +void * +cell_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) { - struct cell_context *cell = cell_context(pipe); - + struct cell_velems_state *velems; assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct cell_velems_state *) MALLOC(sizeof(struct cell_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + +void +cell_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + struct cell_context *cell = cell_context(pipe); + struct cell_velems_state *cell_velems = (struct cell_velems_state *) velems; - memcpy(cell->vertex_element, elements, count * sizeof(elements[0])); - cell->num_vertex_elements = count; + cell->velems = cell_velems; cell->dirty |= CELL_NEW_VERTEX; - draw_set_vertex_elements(cell->draw, count, elements); + if (cell_velems) + draw_set_vertex_elements(cell->draw, cell_velems->count, cell_velems->velem); +} + +void +cell_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); } @@ -75,5 +95,7 @@ void cell_init_vertex_functions(struct cell_context *cell) { cell->pipe.set_vertex_buffers = cell_set_vertex_buffers; - cell->pipe.set_vertex_elements = cell_set_vertex_elements; + cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state; + cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state; + cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state; } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index fad290dfa0..5b169afaf8 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -34,20 +34,23 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" -#include "util/u_simple_screen.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "cell_context.h" +#include "cell_screen.h" #include "cell_state.h" #include "cell_texture.h" +#include "state_tracker/sw_winsys.h" -static void -cell_texture_layout(struct cell_texture *ct) + +static boolean +cell_texture_layout(struct pipe_screen *screen, + struct cell_texture *ct) { struct pipe_texture *pt = &ct->base; unsigned level; @@ -83,9 +86,35 @@ cell_texture_layout(struct cell_texture *ct) height = u_minify(height, 1); depth = u_minify(depth, 1); } + + ct->data = align_malloc(ct->buffer_size, 16); + + return ct->data != NULL; } +/** + * Texture layout for simple color buffers. + */ +static boolean +cell_displaytarget_layout(struct pipe_screen *screen, + struct cell_texture * ct) +{ + struct sw_winsys *winsys = cell_screen(screen)->winsys; + + /* Round up the surface size to a multiple of the tile size? + */ + ct->dt = winsys->displaytarget_create(winsys, + ct->base->tex_usage, + ct->base.format, + ct->base.width0, + ct->base.height0, + 16, + &ct->dt_stride ); + + return ct->dt != NULL; +} + static struct pipe_texture * cell_texture_create(struct pipe_screen *screen, const struct pipe_texture *templat) @@ -98,31 +127,46 @@ cell_texture_create(struct pipe_screen *screen, pipe_reference_init(&ct->base.reference, 1); ct->base.screen = screen; - cell_texture_layout(ct); + /* Create both a displaytarget (linear) and regular texture + * (twiddled). Convert twiddled->linear at flush_frontbuffer time. + */ + if (ct->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if (!cell_displaytarget_layout(screen, ct)) + goto fail; + } - ct->buffer = screen->buffer_create(screen, 32, PIPE_BUFFER_USAGE_PIXEL, - ct->buffer_size); + if (!cell_texture_layout(screen, ct)) + goto fail; - if (!ct->buffer) { - FREE(ct); - return NULL; + return &ct->base; + +fail: + if (ct->dt) { + struct sw_winsys *winsys = cell_screen(screen)->winsys; + winsys->displaytarget_destroy(winsys, ct->dt); } - return &ct->base; + FREE(ct); + + return NULL; } static void cell_texture_destroy(struct pipe_texture *pt) { + struct cell_screen *screen = cell_screen(pt->screen); + struct sw_winsys *winsys = screen->winsys; struct cell_texture *ct = cell_texture(pt); - if (ct->mapped) { - pipe_buffer_unmap(ct->buffer->screen, ct->buffer); - ct->mapped = NULL; + if (ct->dt) { + /* display target */ + winsys->displaytarget_destroy(winsys, ct->dt); } - pipe_buffer_reference(&ct->buffer, NULL); + align_free(ct->data); FREE(ct); } @@ -312,7 +356,7 @@ cell_tex_surface_destroy(struct pipe_surface *surf) * back out for glGetTexImage). */ static struct pipe_transfer * -cell_get_tex_transfer(struct pipe_screen *screen, +cell_get_tex_transfer(struct pipe_context *ctx, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -359,7 +403,7 @@ cell_get_tex_transfer(struct pipe_screen *screen, static void -cell_tex_transfer_destroy(struct pipe_transfer *t) +cell_tex_transfer_destroy(struct pipe_context *ctx, struct pipe_transfer *t) { struct cell_transfer *transfer = cell_transfer(t); /* Effectively do the texture_update work here - if texture images @@ -376,7 +420,7 @@ cell_tex_transfer_destroy(struct pipe_transfer *t) * Return pointer to texture image data in linear layout. */ static void * -cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) +cell_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct cell_transfer *ctrans = cell_transfer(transfer); struct pipe_texture *pt = transfer->texture; @@ -389,10 +433,8 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) assert(transfer->texture); - if (!ct->mapped) { - /* map now */ - ct->mapped = pipe_buffer_map(screen, ct->buffer, - pipe_transfer_buffer_flags(transfer)); + if (ct->mapped == NULL) { + ct->mapped = ct->data; } /* @@ -430,7 +472,7 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer) * to tiled data. */ static void -cell_transfer_unmap(struct pipe_screen *screen, +cell_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct cell_transfer *ctrans = cell_transfer(transfer); @@ -442,9 +484,8 @@ cell_transfer_unmap(struct pipe_screen *screen, const uint stride = ct->stride[level]; if (!ct->mapped) { - /* map now */ - ct->mapped = pipe_buffer_map(screen, ct->buffer, - PIPE_BUFFER_USAGE_CPU_READ); + assert(0); + return; } if (transfer->usage & PIPE_TRANSFER_WRITE) { @@ -467,6 +508,50 @@ cell_transfer_unmap(struct pipe_screen *screen, } + +/* This used to be overriden by the co-state tracker, but really needs + * to be active with sw_winsys. + * + * Contrasting with llvmpipe and softpipe, this is the only place + * where we use the ct->dt display target in any real sense. + * + * Basically just untwiddle our local data into the linear + * displaytarget. + */ +static void +cell_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *surface, + void *context_private) +{ + struct cell_screen *screen = cell_screen(_screen); + struct sw_winsys *winsys = screen->winsys; + struct cell_texture *ct = cell_texture(surface->texture); + + if (!ct->dt) + return; + + /* Need to untwiddle from our internal representation here: + */ + { + unsigned *map = winsys->displaytarget_map(winsys, ct->dt, + (PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE)); + unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]); + + untwiddle_image_uint(surface->width, + surface->height, + TILE_SIZE, + map, + ct->dt_stride, + src); + + winsys->displaytarget_unmap(winsys, ct->dt); + } + + winsys->displaytarget_display(winsys, ct->dt, context_private); +} + + void cell_init_screen_texture_funcs(struct pipe_screen *screen) { @@ -476,9 +561,14 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen) screen->get_tex_surface = cell_get_tex_surface; screen->tex_surface_destroy = cell_tex_surface_destroy; - screen->get_tex_transfer = cell_get_tex_transfer; - screen->tex_transfer_destroy = cell_tex_transfer_destroy; + screen->flush_frontbuffer = cell_flush_frontbuffer; +} - screen->transfer_map = cell_transfer_map; - screen->transfer_unmap = cell_transfer_unmap; +void +cell_init_texture_transfer_funcs(struct cell_context *cell) +{ + cell->pipe.get_tex_transfer = cell_get_tex_transfer; + cell->pipe.tex_transfer_destroy = cell_tex_transfer_destroy; + cell->pipe.transfer_map = cell_transfer_map; + cell->pipe.transfer_unmap = cell_transfer_unmap; } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index 3ffc0bfdb5..ac0b916775 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -28,6 +28,7 @@ #ifndef CELL_TEXTURE_H #define CELL_TEXTURE_H +#include "cell/common.h" struct cell_context; struct pipe_texture; @@ -43,8 +44,20 @@ struct cell_texture unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS]; unsigned long stride[CELL_MAX_TEXTURE_LEVELS]; - /** The tiled texture data is held in this buffer */ - struct pipe_buffer *buffer; + /** + * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET + * usage. + */ + struct sw_displaytarget *dt; + unsigned dt_stride; + + /** + * Malloc'ed data for regular textures, or a mapping to dt above. + */ + void *data; + + /* Size of the linear buffer?? + */ unsigned long buffer_size; /** The buffer above, mapped. This is the memory from which the @@ -82,5 +95,7 @@ cell_transfer(struct pipe_transfer *pt) extern void cell_init_screen_texture_funcs(struct pipe_screen *screen); +extern void +cell_init_texture_transfer_funcs(struct cell_context *cell); #endif /* CELL_TEXTURE_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c index cf8cd41159..3d389d6ea3 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c @@ -31,7 +31,6 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "util/u_simple_screen.h" #include "util/u_math.h" #include "cell_context.h" diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c index 79f1fb7fb2..f16cabc027 100644 --- a/src/gallium/drivers/cell/spu/spu_command.c +++ b/src/gallium/drivers/cell/spu/spu_command.c @@ -337,8 +337,8 @@ cmd_state_framebuffer(const struct cell_command_framebuffer *cmd) spu.fb.zsize = 4; spu.fb.zscale = (float) 0xffffffffu; break; - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_Z24X8_UNORM: spu.fb.zsize = 4; diff --git a/src/gallium/drivers/cell/spu/spu_per_fragment_op.c b/src/gallium/drivers/cell/spu/spu_per_fragment_op.c index 2c9e7458af..3b9566042a 100644 --- a/src/gallium/drivers/cell/spu/spu_per_fragment_op.c +++ b/src/gallium/drivers/cell/spu/spu_per_fragment_op.c @@ -138,13 +138,13 @@ spu_fallback_fragment_ops(uint x, uint y, if (spu.depth_stencil_alpha.stencil[0].enabled) { /* do stencil test */ - ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z24S8_UNORM); + ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED); } else if (spu.depth_stencil_alpha.depth.enabled) { /* do depth test */ - ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z24S8_UNORM || + ASSERT(spu.fb.depth_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || spu.fb.depth_format == PIPE_FORMAT_Z24X8_UNORM); vector unsigned int ifragZ; |