diff options
Diffstat (limited to 'src/gallium/drivers')
170 files changed, 4595 insertions, 4274 deletions
diff --git a/src/gallium/drivers/cell/ppu/Makefile b/src/gallium/drivers/cell/ppu/Makefile index c92f8e5cba2..8769b826b5f 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 00000000000..f56a28d62e2 --- /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 e227e065ff3..ef0a8a70e59 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 5bff9869fd0..f6cb1fc9be7 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 a77cc5b9067..28f80b82cd5 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; @@ -125,8 +131,6 @@ struct cell_context 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 bffd0fac6fe..15d4e8338f4 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 e10071529a8..035ef41b898 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_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index 3d8b4409c75..dce10ae7f86 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -292,17 +292,23 @@ cell_set_sampler_textures(struct pipe_context *pipe, 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 +316,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 +335,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 +353,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; } } 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 00000000000..7e2e093565d --- /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 a43f8638dcd..31fd963d19a 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 * @@ -134,19 +136,28 @@ cell_is_format_supported( struct pipe_screen *screen, unsigned tex_usage, unsigned geom_flags ) { - /* cell supports most formats, XXX for now anyway */ + struct sw_winsys *winsys = cell_screen(screen)->winsys; + if (format == PIPE_FORMAT_DXT5_RGBA || format == PIPE_FORMAT_A8B8G8R8_SRGB) return FALSE; - else - return TRUE; + + if (tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + if (!winsys->is_displaytarget_format_supported(winsys, format)) + return FALSE; + } + + /* This is often a lie. Pull in logic from llvmpipe to fix. + */ + return TRUE; } 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); @@ -155,32 +166,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 c7e15889d66..baff9d3b7d4 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 a59c7828ac3..424e2628a95 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 9b2f86fdfba..9e29ddc2d45 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 fbe55c84721..9510ea9ac2b 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 fad290dfa0e..c65c3b4f885 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,34 @@ 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.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 +126,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 +355,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 +402,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 +419,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 +432,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 +471,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 +483,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 +507,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 +560,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 3ffc0bfdb51..ac0b9167750 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 cf8cd411598..3d389d6ea36 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/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index 2ccc5d3e605..659e40cbf03 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -27,7 +27,6 @@ #include "pipe/p_defines.h" -#include "util/u_simple_screen.h" #include "util/u_memory.h" #include "pipe/p_context.h" diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h index bb1a168ea7a..4a754465bbe 100644 --- a/src/gallium/drivers/failover/fo_context.h +++ b/src/gallium/drivers/failover/fo_context.h @@ -78,6 +78,7 @@ struct failover_context { const struct fo_state *rasterizer; const struct fo_state *fragment_shader; const struct fo_state *vertex_shader; + const struct fo_state *vertex_elements; struct pipe_blend_color blend_color; struct pipe_stencil_ref stencil_ref; @@ -89,10 +90,8 @@ struct failover_context { struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS]; uint num_vertex_buffers; - uint num_vertex_elements; void *sw_sampler_state[PIPE_MAX_SAMPLERS]; void *hw_sampler_state[PIPE_MAX_SAMPLERS]; diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c index 970606a3f50..0247fb803b2 100644 --- a/src/gallium/drivers/failover/fo_state.c +++ b/src/gallium/drivers/failover/fo_state.c @@ -255,9 +255,52 @@ failover_delete_vs_state(struct pipe_context *pipe, free(state); } + + +static void * +failover_create_vertex_elements_state( struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *velems ) +{ + struct fo_state *state = malloc(sizeof(struct fo_state)); + struct failover_context *failover = failover_context(pipe); + + state->sw_state = failover->sw->create_vertex_elements_state(failover->sw, count, velems); + state->hw_state = failover->hw->create_vertex_elements_state(failover->hw, count, velems); + + return state; +} + +static void +failover_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems ) +{ + struct failover_context *failover = failover_context(pipe); + struct fo_state *state = (struct fo_state*)velems; + + failover->vertex_elements = state; + failover->dirty |= FO_NEW_VERTEX_ELEMENT; + failover->sw->bind_vertex_elements_state( failover->sw, velems ); + failover->hw->bind_vertex_elements_state( failover->hw, velems ); +} + +static void +failover_delete_vertex_elements_state( struct pipe_context *pipe, + void *velems ) +{ + struct fo_state *state = (struct fo_state*)velems; + struct failover_context *failover = failover_context(pipe); + + failover->sw->delete_vertex_elements_state(failover->sw, state->sw_state); + failover->hw->delete_vertex_elements_state(failover->hw, state->hw_state); + state->sw_state = 0; + state->hw_state = 0; + free(state); +} + static void failover_set_polygon_stipple( struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple ) + const struct pipe_poly_stipple *stipple ) { struct failover_context *failover = failover_context(pipe); @@ -490,22 +533,6 @@ failover_set_vertex_buffers(struct pipe_context *pipe, } -static void -failover_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *vertex_elements) -{ - struct failover_context *failover = failover_context(pipe); - - memcpy(failover->vertex_elements, vertex_elements, - count * sizeof(vertex_elements[0])); - - failover->dirty |= FO_NEW_VERTEX_ELEMENT; - failover->num_vertex_elements = count; - failover->sw->set_vertex_elements( failover->sw, count, vertex_elements ); - failover->hw->set_vertex_elements( failover->hw, count, vertex_elements ); -} - void failover_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, @@ -543,6 +570,9 @@ failover_init_state_functions( struct failover_context *failover ) failover->pipe.create_vs_state = failover_create_vs_state; failover->pipe.bind_vs_state = failover_bind_vs_state; failover->pipe.delete_vs_state = failover_delete_vs_state; + failover->pipe.create_vertex_elements_state = failover_create_vertex_elements_state; + failover->pipe.bind_vertex_elements_state = failover_bind_vertex_elements_state; + failover->pipe.delete_vertex_elements_state = failover_delete_vertex_elements_state; failover->pipe.set_blend_color = failover_set_blend_color; failover->pipe.set_stencil_ref = failover_set_stencil_ref; @@ -554,6 +584,5 @@ failover_init_state_functions( struct failover_context *failover ) failover->pipe.set_vertex_sampler_textures = failover_set_vertex_sampler_textures; failover->pipe.set_viewport_state = failover_set_viewport_state; failover->pipe.set_vertex_buffers = failover_set_vertex_buffers; - failover->pipe.set_vertex_elements = failover_set_vertex_elements; failover->pipe.set_constant_buffer = failover_set_constant_buffer; } diff --git a/src/gallium/drivers/failover/fo_state_emit.c b/src/gallium/drivers/failover/fo_state_emit.c index 5c000808425..09ca1944971 100644 --- a/src/gallium/drivers/failover/fo_state_emit.c +++ b/src/gallium/drivers/failover/fo_state_emit.c @@ -81,6 +81,10 @@ failover_state_emit( struct failover_context *failover ) failover->sw->bind_vs_state( failover->sw, failover->vertex_shader->sw_state ); + if (failover->dirty & FO_NEW_VERTEX_ELEMENT) + failover->sw->bind_vertex_elements_state( failover->sw, + failover->vertex_elements->sw_state ); + if (failover->dirty & FO_NEW_STIPPLE) failover->sw->set_polygon_stipple( failover->sw, &failover->poly_stipple ); @@ -116,11 +120,5 @@ failover_state_emit( struct failover_context *failover ) failover->vertex_buffers ); } - if (failover->dirty & FO_NEW_VERTEX_ELEMENT) { - failover->sw->set_vertex_elements( failover->sw, - failover->num_vertex_elements, - failover->vertex_elements ); - } - failover->dirty = 0; } diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 3d45a22b7e7..130519ffa50 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -221,6 +221,7 @@ i915_create_context(struct pipe_screen *screen, void *priv) i915_init_surface_functions(i915); i915_init_state_functions(i915); i915_init_flush_functions(i915); + i915_init_texture_functions(i915); draw_install_aaline_stage(i915->draw, &i915->base); draw_install_aapoint_stage(i915->draw, &i915->base); diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index da769e7b290..039165b63f5 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -148,7 +148,7 @@ struct i915_state /** Describes the current hardware vertex layout */ struct vertex_info vertex_info; - + unsigned id; /* track lost context events */ }; @@ -187,6 +187,14 @@ struct i915_sampler_state { unsigned maxlod; }; +struct i915_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; + +#define I915_MAX_TEXTURE_2D_LEVELS 11 /* max 1024x1024 */ +#define I915_MAX_TEXTURE_3D_LEVELS 8 /* max 128x128x128 */ + struct i915_texture { struct pipe_texture base; @@ -199,7 +207,7 @@ struct i915_texture { unsigned sw_tiled; /**< tiled with software flags */ unsigned hw_tiled; /**< tiled with hardware fences */ - unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS]; + unsigned nr_images[I915_MAX_TEXTURE_2D_LEVELS]; /* Explicitly store the offset of each image for each cube face or * depth value. Pretty much have to accept that hardware formats @@ -207,7 +215,7 @@ struct i915_texture { * compute the offsets of depth/cube images within a mipmap level, * so have to store them as a lookup table: */ - unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; /**< array [depth] of offsets */ + unsigned *image_offset[I915_MAX_TEXTURE_2D_LEVELS]; /**< array [depth] of offsets */ /* The data is held here: */ @@ -247,7 +255,6 @@ struct i915_context unsigned num_samplers; unsigned num_textures; - unsigned num_vertex_elements; unsigned num_vertex_buffers; struct intel_batchbuffer *batch; @@ -343,6 +350,12 @@ struct pipe_context *i915_create_context(struct pipe_screen *screen, /*********************************************************************** + * i915_texture.c + */ +void i915_init_texture_functions(struct i915_context *i915 ); + + +/*********************************************************************** * Inline conversion functions. These are better-typed than the * macros used previously: */ diff --git a/src/gallium/drivers/i915/i915_debug_fp.c b/src/gallium/drivers/i915/i915_debug_fp.c index 066e7392d18..f41c51f2991 100644 --- a/src/gallium/drivers/i915/i915_debug_fp.c +++ b/src/gallium/drivers/i915/i915_debug_fp.c @@ -28,7 +28,6 @@ #include "i915_reg.h" #include "i915_debug.h" -#include "util/u_simple_screen.h" #include "util/u_debug.h" diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 72bd2635506..e5bf4a20bd0 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -116,11 +116,11 @@ i915_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 11; /* max 1024x1024 */ + return I915_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 8; /* max 128x128x128 */ + return I915_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 11; /* max 1024x1024 */ + return I915_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 62169918e2b..377d8425a5c 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -742,21 +742,45 @@ static void i915_set_vertex_buffers(struct pipe_context *pipe, draw_set_vertex_buffers(i915->draw, count, buffers); } -static void i915_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements) +static void * +i915_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) +{ + struct i915_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct i915_velems_state *) MALLOC(sizeof(struct i915_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + +static void +i915_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) { struct i915_context *i915 = i915_context(pipe); + struct i915_velems_state *i915_velems = (struct i915_velems_state *) velems; + /* Because we change state before the draw_set_vertex_buffers call * we need a flush here, just to be sure. */ draw_flush(i915->draw); - i915->num_vertex_elements = count; /* pass-through to draw module */ - draw_set_vertex_elements(i915->draw, count, elements); + if (i915_velems) { + draw_set_vertex_elements(i915->draw, + i915_velems->count, i915_velems->velem); + } } +static void +i915_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} void i915_init_state_functions( struct i915_context *i915 ) @@ -782,6 +806,9 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.create_vs_state = i915_create_vs_state; i915->base.bind_vs_state = i915_bind_vs_state; i915->base.delete_vs_state = i915_delete_vs_state; + i915->base.create_vertex_elements_state = i915_create_vertex_elements_state; + i915->base.bind_vertex_elements_state = i915_bind_vertex_elements_state; + i915->base.delete_vertex_elements_state = i915_delete_vertex_elements_state; i915->base.set_blend_color = i915_set_blend_color; i915->base.set_stencil_ref = i915_set_stencil_ref; @@ -794,5 +821,4 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.set_fragment_sampler_textures = i915_set_sampler_textures; i915->base.set_viewport_state = i915_set_viewport_state; i915->base.set_vertex_buffers = i915_set_vertex_buffers; - i915->base.set_vertex_elements = i915_set_vertex_elements; } diff --git a/src/gallium/drivers/i915/i915_texture.c b/src/gallium/drivers/i915/i915_texture.c index 7ba222c78b7..b252fb5330c 100644 --- a/src/gallium/drivers/i915/i915_texture.c +++ b/src/gallium/drivers/i915/i915_texture.c @@ -96,7 +96,7 @@ i915_miptree_set_level_info(struct i915_texture *tex, unsigned nr_images, unsigned w, unsigned h, unsigned d) { - assert(level < PIPE_MAX_TEXTURE_LEVELS); + assert(level < Elements(tex->nr_images)); tex->nr_images[level] = nr_images; @@ -219,12 +219,12 @@ i915_miptree_layout_2d(struct i915_texture *tex) unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->width0); /* used for scanouts that need special layouts */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if (pt->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) if (i915_scanout_layout(tex)) return; - /* for shared buffers we use something very like scanout */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) + /* shared buffers needs to be compatible with X servers */ + if (pt->tex_usage & PIPE_TEXTURE_USAGE_SHARED) if (i915_display_target_layout(tex)) return; @@ -369,12 +369,12 @@ i945_miptree_layout_2d(struct i915_texture *tex) unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0); /* used for scanouts that need special layouts */ - if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) if (i915_scanout_layout(tex)) return; - /* for shared buffers we use some very like scanout */ - if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) + /* shared buffers needs to be compatible with X servers */ + if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_SHARED) if (i915_display_target_layout(tex)) return; @@ -642,7 +642,7 @@ i915_texture_create(struct pipe_screen *screen, /* for scanouts and cursors, cursors arn't scanouts */ - if (templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY && templat->width0 != 64) + if (templat->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT && templat->width0 != 64) buf_usage = INTEL_NEW_SCANOUT; else buf_usage = INTEL_NEW_TEXTURE; @@ -673,19 +673,24 @@ fail: } static struct pipe_texture * -i915_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) +i915_texture_from_handle(struct pipe_screen * screen, + const struct pipe_texture *templat, + struct winsys_handle *whandle) { -#if 0 + struct i915_screen *is = i915_screen(screen); struct i915_texture *tex; + struct intel_winsys *iws = is->iws; + struct intel_buffer *buffer; + unsigned stride; + assert(screen); + buffer = iws->buffer_from_handle(iws, whandle, &stride); + /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { + if (templat->target != PIPE_TEXTURE_2D || + templat->last_level != 0 || + templat->depth0 != 1) { return NULL; } @@ -693,23 +698,33 @@ i915_texture_blanket(struct pipe_screen * screen, if (!tex) return NULL; - tex->base = *base; + tex->base = *templat; pipe_reference_init(&tex->base.reference, 1); tex->base.screen = screen; - tex->stride = stride[0]; + tex->stride = stride; - i915_miptree_set_level_info(tex, 0, 1, base->width0, base->height0, 1); + i915_miptree_set_level_info(tex, 0, 1, templat->width0, templat->height0, 1); i915_miptree_set_image_offset(tex, 0, 0, 0, 0); - pipe_buffer_reference(&tex->buffer, buffer); + tex->buffer = buffer; return &tex->base; -#else - return NULL; -#endif } +static boolean +i915_texture_get_handle(struct pipe_screen * screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct i915_screen *is = i915_screen(screen); + struct i915_texture *tex = (struct i915_texture *)texture; + struct intel_winsys *iws = is->iws; + + return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride); +} + + static void i915_texture_destroy(struct pipe_texture *pt) { @@ -723,7 +738,7 @@ i915_texture_destroy(struct pipe_texture *pt) iws->buffer_destroy(iws, tex->buffer); - for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) + for (i = 0; i < Elements(tex->image_offset); i++) if (tex->image_offset[i]) FREE(tex->image_offset[i]); @@ -780,12 +795,12 @@ i915_tex_surface_destroy(struct pipe_surface *surf) /* - * Screen transfer functions + * Texture transfer functions */ -static struct pipe_transfer* -i915_get_tex_transfer(struct pipe_screen *screen, +static struct pipe_transfer * +i915_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, @@ -822,7 +837,7 @@ i915_get_tex_transfer(struct pipe_screen *screen, } static void * -i915_transfer_map(struct pipe_screen *screen, +i915_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct i915_texture *tex = (struct i915_texture *)transfer->texture; @@ -844,7 +859,7 @@ i915_transfer_map(struct pipe_screen *screen, } static void -i915_transfer_unmap(struct pipe_screen *screen, +i915_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct i915_texture *tex = (struct i915_texture *)transfer->texture; @@ -853,7 +868,8 @@ i915_transfer_unmap(struct pipe_screen *screen, } static void -i915_tex_transfer_destroy(struct pipe_transfer *trans) +i915_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *trans) { pipe_texture_reference(&trans->texture, NULL); FREE(trans); @@ -864,67 +880,22 @@ i915_tex_transfer_destroy(struct pipe_transfer *trans) * Other texture functions */ +void +i915_init_texture_functions(struct i915_context *i915 ) +{ + i915->base.get_tex_transfer = i915_get_tex_transfer; + i915->base.transfer_map = i915_transfer_map; + i915->base.transfer_unmap = i915_transfer_unmap; + i915->base.tex_transfer_destroy = i915_tex_transfer_destroy; +} void i915_init_screen_texture_functions(struct i915_screen *is) { is->base.texture_create = i915_texture_create; - is->base.texture_blanket = i915_texture_blanket; + is->base.texture_from_handle = i915_texture_from_handle; + is->base.texture_get_handle = i915_texture_get_handle; is->base.texture_destroy = i915_texture_destroy; is->base.get_tex_surface = i915_get_tex_surface; is->base.tex_surface_destroy = i915_tex_surface_destroy; - is->base.get_tex_transfer = i915_get_tex_transfer; - is->base.transfer_map = i915_transfer_map; - is->base.transfer_unmap = i915_transfer_unmap; - is->base.tex_transfer_destroy = i915_tex_transfer_destroy; -} - -struct pipe_texture * -i915_texture_blanket_intel(struct pipe_screen *screen, - struct pipe_texture *base, - unsigned stride, - struct intel_buffer *buffer) -{ - struct i915_texture *tex; - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - tex = CALLOC_STRUCT(i915_texture); - if (!tex) - return NULL; - - tex->base = *base; - pipe_reference_init(&tex->base.reference, 1); - tex->base.screen = screen; - - tex->stride = stride; - - i915_miptree_set_level_info(tex, 0, 1, base->width0, base->height0, 1); - i915_miptree_set_image_offset(tex, 0, 0, 0, 0); - - tex->buffer = buffer; - - return &tex->base; -} - -boolean -i915_get_texture_buffer_intel(struct pipe_texture *texture, - struct intel_buffer **buffer, - unsigned *stride) -{ - struct i915_texture *tex = (struct i915_texture *)texture; - - if (!texture) - return FALSE; - - *stride = tex->stride; - *buffer = tex->buffer; - - return TRUE; } diff --git a/src/gallium/drivers/i915/intel_winsys.h b/src/gallium/drivers/i915/intel_winsys.h index b3a802b0e29..00fd0c1efea 100644 --- a/src/gallium/drivers/i915/intel_winsys.h +++ b/src/gallium/drivers/i915/intel_winsys.h @@ -33,6 +33,7 @@ struct intel_buffer; struct intel_batchbuffer; struct pipe_texture; struct pipe_fence_handle; +struct winsys_handle; enum intel_buffer_usage { @@ -129,6 +130,25 @@ struct intel_winsys { enum intel_buffer_type type); /** + * Creates a buffer from a handle. + * Used to implement pipe_screen::texture_from_handle. + * Also provides the stride information needed for the + * texture via the stride argument. + */ + struct intel_buffer *(*buffer_from_handle)(struct intel_winsys *iws, + struct winsys_handle *whandle, + unsigned *stride); + + /** + * Used to implement pipe_screen::texture_get_handle. + * The winsys might need the stride information. + */ + boolean (*buffer_get_handle)(struct intel_winsys *iws, + struct intel_buffer *buffer, + struct winsys_handle *whandle, + unsigned stride); + + /** * Fence a buffer with a fence reg. * Not to be confused with pipe_fence_handle. */ @@ -204,23 +224,4 @@ struct intel_winsys { struct pipe_screen *i915_create_screen(struct intel_winsys *iws, unsigned pci_id); -/** - * Get the intel_winsys buffer backing the texture. - * - * TODO UGLY - */ -boolean i915_get_texture_buffer_intel(struct pipe_texture *texture, - struct intel_buffer **buffer, - unsigned *stride); - -/** - * Wrap a intel_winsys buffer with a texture blanket. - * - * TODO UGLY - */ -struct pipe_texture * i915_texture_blanket_intel(struct pipe_screen *screen, - struct pipe_texture *tmplt, - unsigned pitch, - struct intel_buffer *buffer); - #endif diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 12cfa7b049c..f5b1a06576b 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -351,7 +351,7 @@ struct brw_vs_prog_data { /* Size == 0 if output either not written, or always [0,0,0,1] */ -struct brw_vs_ouput_sizes { +struct brw_vs_output_sizes { GLubyte output_size[PIPE_MAX_SHADER_OUTPUTS]; }; @@ -546,14 +546,13 @@ struct brw_context const struct brw_blend_state *blend; const struct brw_rasterizer_state *rast; const struct brw_depth_stencil_state *zstencil; + const struct brw_vertex_element_packet *velems; const struct brw_sampler *sampler[PIPE_MAX_SAMPLERS]; unsigned num_samplers; struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; - unsigned num_vertex_elements; unsigned num_textures; unsigned num_vertex_buffers; diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c index 9f136eec71c..0820ba20a08 100644 --- a/src/gallium/drivers/i965/brw_draw_upload.c +++ b/src/gallium/drivers/i965/brw_draw_upload.c @@ -42,141 +42,6 @@ -static unsigned brw_translate_surface_format( unsigned id ) -{ - switch (id) { - case PIPE_FORMAT_R64_FLOAT: - return BRW_SURFACEFORMAT_R64_FLOAT; - case PIPE_FORMAT_R64G64_FLOAT: - return BRW_SURFACEFORMAT_R64G64_FLOAT; - case PIPE_FORMAT_R64G64B64_FLOAT: - return BRW_SURFACEFORMAT_R64G64B64_FLOAT; - case PIPE_FORMAT_R64G64B64A64_FLOAT: - return BRW_SURFACEFORMAT_R64G64B64A64_FLOAT; - - case PIPE_FORMAT_R32_FLOAT: - return BRW_SURFACEFORMAT_R32_FLOAT; - case PIPE_FORMAT_R32G32_FLOAT: - return BRW_SURFACEFORMAT_R32G32_FLOAT; - case PIPE_FORMAT_R32G32B32_FLOAT: - return BRW_SURFACEFORMAT_R32G32B32_FLOAT; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; - - case PIPE_FORMAT_R32_UNORM: - return BRW_SURFACEFORMAT_R32_UNORM; - case PIPE_FORMAT_R32G32_UNORM: - return BRW_SURFACEFORMAT_R32G32_UNORM; - case PIPE_FORMAT_R32G32B32_UNORM: - return BRW_SURFACEFORMAT_R32G32B32_UNORM; - case PIPE_FORMAT_R32G32B32A32_UNORM: - return BRW_SURFACEFORMAT_R32G32B32A32_UNORM; - - case PIPE_FORMAT_R32_USCALED: - return BRW_SURFACEFORMAT_R32_USCALED; - case PIPE_FORMAT_R32G32_USCALED: - return BRW_SURFACEFORMAT_R32G32_USCALED; - case PIPE_FORMAT_R32G32B32_USCALED: - return BRW_SURFACEFORMAT_R32G32B32_USCALED; - case PIPE_FORMAT_R32G32B32A32_USCALED: - return BRW_SURFACEFORMAT_R32G32B32A32_USCALED; - - case PIPE_FORMAT_R32_SNORM: - return BRW_SURFACEFORMAT_R32_SNORM; - case PIPE_FORMAT_R32G32_SNORM: - return BRW_SURFACEFORMAT_R32G32_SNORM; - case PIPE_FORMAT_R32G32B32_SNORM: - return BRW_SURFACEFORMAT_R32G32B32_SNORM; - case PIPE_FORMAT_R32G32B32A32_SNORM: - return BRW_SURFACEFORMAT_R32G32B32A32_SNORM; - - case PIPE_FORMAT_R32_SSCALED: - return BRW_SURFACEFORMAT_R32_SSCALED; - case PIPE_FORMAT_R32G32_SSCALED: - return BRW_SURFACEFORMAT_R32G32_SSCALED; - case PIPE_FORMAT_R32G32B32_SSCALED: - return BRW_SURFACEFORMAT_R32G32B32_SSCALED; - case PIPE_FORMAT_R32G32B32A32_SSCALED: - return BRW_SURFACEFORMAT_R32G32B32A32_SSCALED; - - case PIPE_FORMAT_R16_UNORM: - return BRW_SURFACEFORMAT_R16_UNORM; - case PIPE_FORMAT_R16G16_UNORM: - return BRW_SURFACEFORMAT_R16G16_UNORM; - case PIPE_FORMAT_R16G16B16_UNORM: - return BRW_SURFACEFORMAT_R16G16B16_UNORM; - case PIPE_FORMAT_R16G16B16A16_UNORM: - return BRW_SURFACEFORMAT_R16G16B16A16_UNORM; - - case PIPE_FORMAT_R16_USCALED: - return BRW_SURFACEFORMAT_R16_USCALED; - case PIPE_FORMAT_R16G16_USCALED: - return BRW_SURFACEFORMAT_R16G16_USCALED; - case PIPE_FORMAT_R16G16B16_USCALED: - return BRW_SURFACEFORMAT_R16G16B16_USCALED; - case PIPE_FORMAT_R16G16B16A16_USCALED: - return BRW_SURFACEFORMAT_R16G16B16A16_USCALED; - - case PIPE_FORMAT_R16_SNORM: - return BRW_SURFACEFORMAT_R16_SNORM; - case PIPE_FORMAT_R16G16_SNORM: - return BRW_SURFACEFORMAT_R16G16_SNORM; - case PIPE_FORMAT_R16G16B16_SNORM: - return BRW_SURFACEFORMAT_R16G16B16_SNORM; - case PIPE_FORMAT_R16G16B16A16_SNORM: - return BRW_SURFACEFORMAT_R16G16B16A16_SNORM; - - case PIPE_FORMAT_R16_SSCALED: - return BRW_SURFACEFORMAT_R16_SSCALED; - case PIPE_FORMAT_R16G16_SSCALED: - return BRW_SURFACEFORMAT_R16G16_SSCALED; - case PIPE_FORMAT_R16G16B16_SSCALED: - return BRW_SURFACEFORMAT_R16G16B16_SSCALED; - case PIPE_FORMAT_R16G16B16A16_SSCALED: - return BRW_SURFACEFORMAT_R16G16B16A16_SSCALED; - - case PIPE_FORMAT_R8_UNORM: - return BRW_SURFACEFORMAT_R8_UNORM; - case PIPE_FORMAT_R8G8_UNORM: - return BRW_SURFACEFORMAT_R8G8_UNORM; - case PIPE_FORMAT_R8G8B8_UNORM: - return BRW_SURFACEFORMAT_R8G8B8_UNORM; - case PIPE_FORMAT_R8G8B8A8_UNORM: - return BRW_SURFACEFORMAT_R8G8B8A8_UNORM; - - case PIPE_FORMAT_R8_USCALED: - return BRW_SURFACEFORMAT_R8_USCALED; - case PIPE_FORMAT_R8G8_USCALED: - return BRW_SURFACEFORMAT_R8G8_USCALED; - case PIPE_FORMAT_R8G8B8_USCALED: - return BRW_SURFACEFORMAT_R8G8B8_USCALED; - case PIPE_FORMAT_R8G8B8A8_USCALED: - return BRW_SURFACEFORMAT_R8G8B8A8_USCALED; - - case PIPE_FORMAT_R8_SNORM: - return BRW_SURFACEFORMAT_R8_SNORM; - case PIPE_FORMAT_R8G8_SNORM: - return BRW_SURFACEFORMAT_R8G8_SNORM; - case PIPE_FORMAT_R8G8B8_SNORM: - return BRW_SURFACEFORMAT_R8G8B8_SNORM; - case PIPE_FORMAT_R8G8B8A8_SNORM: - return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; - - case PIPE_FORMAT_R8_SSCALED: - return BRW_SURFACEFORMAT_R8_SSCALED; - case PIPE_FORMAT_R8G8_SSCALED: - return BRW_SURFACEFORMAT_R8G8_SSCALED; - case PIPE_FORMAT_R8G8B8_SSCALED: - return BRW_SURFACEFORMAT_R8G8B8_SSCALED; - case PIPE_FORMAT_R8G8B8A8_SSCALED: - return BRW_SURFACEFORMAT_R8G8B8A8_SSCALED; - - default: - assert(0); - return 0; - } -} - static unsigned get_index_type(int type) { switch (type) { @@ -315,75 +180,16 @@ static int brw_emit_vertex_buffers( struct brw_context *brw ) - static int brw_emit_vertex_elements(struct brw_context *brw) { - GLuint nr = brw->curr.num_vertex_elements; - GLuint i; + const struct brw_vertex_element_packet *brw_velems = brw->curr.velems; + unsigned size = brw_velems->header.length + 2; + /* why is this here */ brw_emit_query_begin(brw); - /* If the VS doesn't read any inputs (calculating vertex position from - * a state variable for some reason, for example), emit a single pad - * VERTEX_ELEMENT struct and bail. - * - * The stale VB state stays in place, but they don't do anything unless - * a VE loads from them. - */ - if (nr == 0) { - BEGIN_BATCH(3, IGNORE_CLIPRECTS); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1); - OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) | - BRW_VE0_VALID | - (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) | - (0 << BRW_VE0_SRC_OFFSET_SHIFT)); - OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) | - (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | - (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | - (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT)); - ADVANCE_BATCH(); - return 0; - } - - /* Now emit vertex element (VEP) state packets. - * - */ - BEGIN_BATCH(1 + nr * 2, IGNORE_CLIPRECTS); - OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + nr * 2) - 2)); - for (i = 0; i < nr; i++) { - const struct pipe_vertex_element *input = &brw->curr.vertex_element[i]; - uint32_t format = brw_translate_surface_format( input->src_format ); - uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC; - uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC; - uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC; - uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC; - - switch (input->nr_components) { - case 0: comp0 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ - case 1: comp1 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ - case 2: comp2 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ - case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT; - break; - } - - OUT_BATCH((input->vertex_buffer_index << BRW_VE0_INDEX_SHIFT) | - BRW_VE0_VALID | - (format << BRW_VE0_FORMAT_SHIFT) | - (input->src_offset << BRW_VE0_SRC_OFFSET_SHIFT)); + brw_batchbuffer_data(brw->batch, brw_velems, size * 4, IGNORE_CLIPRECTS); - if (BRW_IS_IGDNG(brw)) - OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) | - (comp1 << BRW_VE1_COMPONENT_1_SHIFT) | - (comp2 << BRW_VE1_COMPONENT_2_SHIFT) | - (comp3 << BRW_VE1_COMPONENT_3_SHIFT)); - else - OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) | - (comp1 << BRW_VE1_COMPONENT_1_SHIFT) | - (comp2 << BRW_VE1_COMPONENT_2_SHIFT) | - (comp3 << BRW_VE1_COMPONENT_3_SHIFT) | - ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT)); - } - ADVANCE_BATCH(); return 0; } @@ -396,10 +202,11 @@ static int brw_emit_vertices( struct brw_context *brw ) if (ret) return ret; + /* XXX should separate this? */ ret = brw_emit_vertex_elements( brw ); if (ret) return ret; - + return 0; } @@ -407,7 +214,8 @@ static int brw_emit_vertices( struct brw_context *brw ) const struct brw_tracked_state brw_vertices = { .dirty = { .mesa = (PIPE_NEW_INDEX_RANGE | - PIPE_NEW_VERTEX_BUFFER), + PIPE_NEW_VERTEX_BUFFER | + PIPE_NEW_VERTEX_ELEMENT), .brw = BRW_NEW_BATCH, .cache = 0, }, diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c index e3c48e31493..d6a840857ec 100644 --- a/src/gallium/drivers/i965/brw_pipe_vertex.c +++ b/src/gallium/drivers/i965/brw_pipe_vertex.c @@ -1,22 +1,251 @@ #include "brw_context.h" +#include "brw_defines.h" +#include "brw_structs.h" +#include "util/u_memory.h" +#include "util/u_format.h" -static void brw_set_vertex_elements( struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements ) + +static unsigned brw_translate_surface_format( unsigned id ) +{ + switch (id) { + case PIPE_FORMAT_R64_FLOAT: + return BRW_SURFACEFORMAT_R64_FLOAT; + case PIPE_FORMAT_R64G64_FLOAT: + return BRW_SURFACEFORMAT_R64G64_FLOAT; + case PIPE_FORMAT_R64G64B64_FLOAT: + return BRW_SURFACEFORMAT_R64G64B64_FLOAT; + case PIPE_FORMAT_R64G64B64A64_FLOAT: + return BRW_SURFACEFORMAT_R64G64B64A64_FLOAT; + + case PIPE_FORMAT_R32_FLOAT: + return BRW_SURFACEFORMAT_R32_FLOAT; + case PIPE_FORMAT_R32G32_FLOAT: + return BRW_SURFACEFORMAT_R32G32_FLOAT; + case PIPE_FORMAT_R32G32B32_FLOAT: + return BRW_SURFACEFORMAT_R32G32B32_FLOAT; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + + case PIPE_FORMAT_R32_UNORM: + return BRW_SURFACEFORMAT_R32_UNORM; + case PIPE_FORMAT_R32G32_UNORM: + return BRW_SURFACEFORMAT_R32G32_UNORM; + case PIPE_FORMAT_R32G32B32_UNORM: + return BRW_SURFACEFORMAT_R32G32B32_UNORM; + case PIPE_FORMAT_R32G32B32A32_UNORM: + return BRW_SURFACEFORMAT_R32G32B32A32_UNORM; + + case PIPE_FORMAT_R32_USCALED: + return BRW_SURFACEFORMAT_R32_USCALED; + case PIPE_FORMAT_R32G32_USCALED: + return BRW_SURFACEFORMAT_R32G32_USCALED; + case PIPE_FORMAT_R32G32B32_USCALED: + return BRW_SURFACEFORMAT_R32G32B32_USCALED; + case PIPE_FORMAT_R32G32B32A32_USCALED: + return BRW_SURFACEFORMAT_R32G32B32A32_USCALED; + + case PIPE_FORMAT_R32_SNORM: + return BRW_SURFACEFORMAT_R32_SNORM; + case PIPE_FORMAT_R32G32_SNORM: + return BRW_SURFACEFORMAT_R32G32_SNORM; + case PIPE_FORMAT_R32G32B32_SNORM: + return BRW_SURFACEFORMAT_R32G32B32_SNORM; + case PIPE_FORMAT_R32G32B32A32_SNORM: + return BRW_SURFACEFORMAT_R32G32B32A32_SNORM; + + case PIPE_FORMAT_R32_SSCALED: + return BRW_SURFACEFORMAT_R32_SSCALED; + case PIPE_FORMAT_R32G32_SSCALED: + return BRW_SURFACEFORMAT_R32G32_SSCALED; + case PIPE_FORMAT_R32G32B32_SSCALED: + return BRW_SURFACEFORMAT_R32G32B32_SSCALED; + case PIPE_FORMAT_R32G32B32A32_SSCALED: + return BRW_SURFACEFORMAT_R32G32B32A32_SSCALED; + + case PIPE_FORMAT_R16_UNORM: + return BRW_SURFACEFORMAT_R16_UNORM; + case PIPE_FORMAT_R16G16_UNORM: + return BRW_SURFACEFORMAT_R16G16_UNORM; + case PIPE_FORMAT_R16G16B16_UNORM: + return BRW_SURFACEFORMAT_R16G16B16_UNORM; + case PIPE_FORMAT_R16G16B16A16_UNORM: + return BRW_SURFACEFORMAT_R16G16B16A16_UNORM; + + case PIPE_FORMAT_R16_USCALED: + return BRW_SURFACEFORMAT_R16_USCALED; + case PIPE_FORMAT_R16G16_USCALED: + return BRW_SURFACEFORMAT_R16G16_USCALED; + case PIPE_FORMAT_R16G16B16_USCALED: + return BRW_SURFACEFORMAT_R16G16B16_USCALED; + case PIPE_FORMAT_R16G16B16A16_USCALED: + return BRW_SURFACEFORMAT_R16G16B16A16_USCALED; + + case PIPE_FORMAT_R16_SNORM: + return BRW_SURFACEFORMAT_R16_SNORM; + case PIPE_FORMAT_R16G16_SNORM: + return BRW_SURFACEFORMAT_R16G16_SNORM; + case PIPE_FORMAT_R16G16B16_SNORM: + return BRW_SURFACEFORMAT_R16G16B16_SNORM; + case PIPE_FORMAT_R16G16B16A16_SNORM: + return BRW_SURFACEFORMAT_R16G16B16A16_SNORM; + + case PIPE_FORMAT_R16_SSCALED: + return BRW_SURFACEFORMAT_R16_SSCALED; + case PIPE_FORMAT_R16G16_SSCALED: + return BRW_SURFACEFORMAT_R16G16_SSCALED; + case PIPE_FORMAT_R16G16B16_SSCALED: + return BRW_SURFACEFORMAT_R16G16B16_SSCALED; + case PIPE_FORMAT_R16G16B16A16_SSCALED: + return BRW_SURFACEFORMAT_R16G16B16A16_SSCALED; + + case PIPE_FORMAT_R8_UNORM: + return BRW_SURFACEFORMAT_R8_UNORM; + case PIPE_FORMAT_R8G8_UNORM: + return BRW_SURFACEFORMAT_R8G8_UNORM; + case PIPE_FORMAT_R8G8B8_UNORM: + return BRW_SURFACEFORMAT_R8G8B8_UNORM; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return BRW_SURFACEFORMAT_R8G8B8A8_UNORM; + + case PIPE_FORMAT_R8_USCALED: + return BRW_SURFACEFORMAT_R8_USCALED; + case PIPE_FORMAT_R8G8_USCALED: + return BRW_SURFACEFORMAT_R8G8_USCALED; + case PIPE_FORMAT_R8G8B8_USCALED: + return BRW_SURFACEFORMAT_R8G8B8_USCALED; + case PIPE_FORMAT_R8G8B8A8_USCALED: + return BRW_SURFACEFORMAT_R8G8B8A8_USCALED; + + case PIPE_FORMAT_R8_SNORM: + return BRW_SURFACEFORMAT_R8_SNORM; + case PIPE_FORMAT_R8G8_SNORM: + return BRW_SURFACEFORMAT_R8G8_SNORM; + case PIPE_FORMAT_R8G8B8_SNORM: + return BRW_SURFACEFORMAT_R8G8B8_SNORM; + case PIPE_FORMAT_R8G8B8A8_SNORM: + return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; + + case PIPE_FORMAT_R8_SSCALED: + return BRW_SURFACEFORMAT_R8_SSCALED; + case PIPE_FORMAT_R8G8_SSCALED: + return BRW_SURFACEFORMAT_R8G8_SSCALED; + case PIPE_FORMAT_R8G8B8_SSCALED: + return BRW_SURFACEFORMAT_R8G8B8_SSCALED; + case PIPE_FORMAT_R8G8B8A8_SSCALED: + return BRW_SURFACEFORMAT_R8G8B8A8_SSCALED; + + default: + assert(0); + return 0; + } +} + +static void brw_translate_vertex_elements(struct brw_context *brw, + struct brw_vertex_element_packet *brw_velems, + const struct pipe_vertex_element *attribs, + unsigned count) +{ + unsigned i; + + /* If the VS doesn't read any inputs (calculating vertex position from + * a state variable for some reason, for example), emit a single pad + * VERTEX_ELEMENT struct and bail. + * + * The stale VB state stays in place, but they don't do anything unless + * a VE loads from them. + */ + brw_velems->header.opcode = CMD_VERTEX_ELEMENT; + + if (count == 0) { + brw_velems->header.length = 1; + brw_velems->ve[0].ve0.src_offset = 0; + brw_velems->ve[0].ve0.src_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; + brw_velems->ve[0].ve0.valid = 1; + brw_velems->ve[0].ve0.vertex_buffer_index = 0; + brw_velems->ve[0].ve1.dst_offset = 0; + brw_velems->ve[0].ve1.vfcomponent0 = BRW_VE1_COMPONENT_STORE_0; + brw_velems->ve[0].ve1.vfcomponent1 = BRW_VE1_COMPONENT_STORE_0; + brw_velems->ve[0].ve1.vfcomponent2 = BRW_VE1_COMPONENT_STORE_0; + brw_velems->ve[0].ve1.vfcomponent3 = BRW_VE1_COMPONENT_STORE_1_FLT; + return; + } + + + /* Now emit vertex element (VEP) state packets. + * + */ + brw_velems->header.length = (1 + count * 2) - 2; + for (i = 0; i < count; i++) { + const struct pipe_vertex_element *input = &attribs[i]; + unsigned nr_components = util_format_get_nr_components(input->src_format); + + uint32_t format = brw_translate_surface_format( input->src_format ); + uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC; + uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC; + uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC; + uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC; + + switch (nr_components) { + case 0: comp0 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ + case 1: comp1 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ + case 2: comp2 = BRW_VE1_COMPONENT_STORE_0; /* fallthrough */ + case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT; + break; + } + + brw_velems->ve[i].ve0.src_offset = input->src_offset; + brw_velems->ve[i].ve0.src_format = format; + brw_velems->ve[i].ve0.valid = 1; + brw_velems->ve[i].ve0.vertex_buffer_index = input->vertex_buffer_index; + brw_velems->ve[i].ve1.vfcomponent0 = comp0; + brw_velems->ve[i].ve1.vfcomponent1 = comp1; + brw_velems->ve[i].ve1.vfcomponent2 = comp2; + brw_velems->ve[i].ve1.vfcomponent3 = comp3; + + if (BRW_IS_IGDNG(brw)) + brw_velems->ve[i].ve1.dst_offset = 0; + else + brw_velems->ve[i].ve1.dst_offset = i * 4; + } +} + +static void* brw_create_vertex_elements_state( struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs ) { + /* note: for the brw_swtnl.c code (if ever we need draw fallback) we'd also need + to store the original data */ struct brw_context *brw = brw_context(pipe); + struct brw_vertex_element_packet *velems; + assert(count <= BRW_VEP_MAX); + velems = (struct brw_vertex_element_packet *) MALLOC(sizeof(struct brw_vertex_element_packet)); + if (velems) { + brw_translate_vertex_elements(brw, velems, attribs, count); + } + return velems; +} - memcpy(brw->curr.vertex_element, elements, count * sizeof(elements[0])); - brw->curr.num_vertex_elements = count; +static void brw_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + struct brw_context *brw = brw_context(pipe); + struct brw_vertex_element_packet *brw_velems = (struct brw_vertex_element_packet *) velems; + + brw->curr.velems = brw_velems; brw->state.dirty.mesa |= PIPE_NEW_VERTEX_ELEMENT; } +static void brw_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} + static void brw_set_vertex_buffers(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_buffer *buffers) + unsigned count, + const struct pipe_vertex_buffer *buffers) { struct brw_context *brw = brw_context(pipe); unsigned i; @@ -49,7 +278,9 @@ void brw_pipe_vertex_init( struct brw_context *brw ) { brw->base.set_vertex_buffers = brw_set_vertex_buffers; - brw->base.set_vertex_elements = brw_set_vertex_elements; + brw->base.create_vertex_elements_state = brw_create_vertex_elements_state; + brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state; + brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state; } diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 66f3aad8b21..cef83ffea80 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -174,11 +174,11 @@ brw_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 11; /* max 1024x1024 */ + return BRW_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 8; /* max 128x128x128 */ + return BRW_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 11; /* max 1024x1024 */ + return BRW_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; diff --git a/src/gallium/drivers/i965/brw_screen.h b/src/gallium/drivers/i965/brw_screen.h index 7226d9228b7..e3a7c64d489 100644 --- a/src/gallium/drivers/i965/brw_screen.h +++ b/src/gallium/drivers/i965/brw_screen.h @@ -100,6 +100,9 @@ struct brw_surface }; +#define BRW_MAX_TEXTURE_2D_LEVELS 11 /* max 1024x1024 */ +#define BRW_MAX_TEXTURE_3D_LEVELS 8 /* max 128x128x128 */ + struct brw_texture { @@ -107,9 +110,9 @@ struct brw_texture struct brw_winsys_buffer *bo; struct brw_surface_state ss; - unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS]; - unsigned level_offset[PIPE_MAX_TEXTURE_LEVELS]; + unsigned *image_offset[BRW_MAX_TEXTURE_2D_LEVELS]; + unsigned nr_images[BRW_MAX_TEXTURE_2D_LEVELS]; + unsigned level_offset[BRW_MAX_TEXTURE_2D_LEVELS]; boolean compressed; unsigned brw_target; @@ -178,6 +181,10 @@ void brw_update_texture( struct brw_screen *brw_screen, struct brw_texture *tex ); +/* brw_screen_texture.h + */ +struct brw_context; +void brw_tex_init( struct brw_context *brw ); void brw_screen_tex_init( struct brw_screen *brw_screen ); void brw_screen_tex_surface_init( struct brw_screen *brw_screen ); diff --git a/src/gallium/drivers/i965/brw_screen_texture.c b/src/gallium/drivers/i965/brw_screen_texture.c index e38fdf1869b..cadcb7cee2a 100644 --- a/src/gallium/drivers/i965/brw_screen_texture.c +++ b/src/gallium/drivers/i965/brw_screen_texture.c @@ -37,6 +37,8 @@ #include "brw_defines.h" #include "brw_structs.h" #include "brw_winsys.h" +#include "brw_context.h" + @@ -231,8 +233,8 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen, goto fail; - if (templ->tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + if (templ->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { buffer_type = BRW_BUFFER_TYPE_SCANOUT; } else { @@ -303,14 +305,121 @@ fail: return NULL; } -static struct pipe_texture *brw_texture_blanket(struct pipe_screen *screen, - const struct pipe_texture *templ, - const unsigned *stride, - struct pipe_buffer *buffer) +static struct pipe_texture * +brw_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *templ, + struct winsys_handle *whandle) { + struct brw_screen *bscreen = brw_screen(screen); + struct brw_texture *tex; + struct brw_winsys_buffer *buffer; + unsigned tiling; + unsigned pitch; + + if (templ->target != PIPE_TEXTURE_2D || + templ->last_level != 0 || + templ->depth0 != 1) + return NULL; + + if (util_format_is_compressed(templ->format)) + return NULL; + + tex = CALLOC_STRUCT(brw_texture); + if (!tex) + return NULL; + + if (bscreen->sws->bo_from_handle(bscreen->sws, whandle, &pitch, &tiling, &buffer) != PIPE_OK) + goto fail; + + memcpy(&tex->base, templ, sizeof *templ); + pipe_reference_init(&tex->base.reference, 1); + tex->base.screen = screen; + + /* XXX: cpp vs. blocksize + */ + tex->cpp = util_format_get_blocksize(tex->base.format); + tex->tiling = tiling; + + make_empty_list(&tex->views[0]); + make_empty_list(&tex->views[1]); + + if (!brw_texture_layout(bscreen, tex)) + goto fail; + + /* XXX Maybe some more checks? */ + if ((pitch / tex->cpp) < tex->pitch) + goto fail; + + tex->pitch = pitch / tex->cpp; + + tex->bo = buffer; + + /* fix this warning */ +#if 0 + if (tex->size > buffer->size) + goto fail; +#endif + + tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + tex->ss.ss0.surface_type = translate_tex_target(tex->base.target); + tex->ss.ss0.surface_format = translate_tex_format(tex->base.format); + assert(tex->ss.ss0.surface_format != BRW_SURFACEFORMAT_INVALID); + + /* This is ok for all textures with channel width 8bit or less: + */ +/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ + + + /* XXX: what happens when tex->bo->offset changes??? + */ + tex->ss.ss1.base_addr = 0; /* reloc */ + tex->ss.ss2.mip_count = tex->base.last_level; + tex->ss.ss2.width = tex->base.width0 - 1; + tex->ss.ss2.height = tex->base.height0 - 1; + + switch (tex->tiling) { + case BRW_TILING_NONE: + tex->ss.ss3.tiled_surface = 0; + tex->ss.ss3.tile_walk = 0; + break; + case BRW_TILING_X: + tex->ss.ss3.tiled_surface = 1; + tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR; + break; + case BRW_TILING_Y: + tex->ss.ss3.tiled_surface = 1; + tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR; + break; + } + + tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1; + tex->ss.ss3.depth = tex->base.depth0 - 1; + + tex->ss.ss4.min_lod = 0; + + return &tex->base; + +fail: + FREE(tex); return NULL; } +static boolean +brw_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct brw_screen *bscreen = brw_screen(screen); + struct brw_texture *tex = brw_texture(texture); + unsigned stride; + + stride = tex->pitch * tex->cpp; + + return bscreen->sws->bo_get_handle(tex->bo, whandle, stride); +} + + + static void brw_texture_destroy(struct pipe_texture *pt) { struct brw_texture *tex = brw_texture(pt); @@ -372,7 +481,7 @@ boolean brw_is_texture_referenced_by_bo( struct brw_screen *brw_screen, */ static struct pipe_transfer* -brw_get_tex_transfer(struct pipe_screen *screen, +brw_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, @@ -407,11 +516,11 @@ brw_get_tex_transfer(struct pipe_screen *screen, } static void * -brw_transfer_map(struct pipe_screen *screen, +brw_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct brw_texture *tex = brw_texture(transfer->texture); - struct brw_winsys_screen *sws = brw_screen(screen)->sws; + struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws; char *map; unsigned usage = transfer->usage; @@ -434,146 +543,37 @@ brw_transfer_map(struct pipe_screen *screen, } static void -brw_transfer_unmap(struct pipe_screen *screen, +brw_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct brw_texture *tex = brw_texture(transfer->texture); - struct brw_winsys_screen *sws = brw_screen(screen)->sws; + struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws; sws->bo_unmap(tex->bo); } static void -brw_tex_transfer_destroy(struct pipe_transfer *trans) +brw_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *trans) { pipe_texture_reference(&trans->texture, NULL); FREE(trans); } -/* - * Functions exported to the winsys - */ - -boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture, - struct brw_winsys_buffer **buffer, - unsigned *stride) -{ - struct brw_texture *tex = brw_texture(texture); - - *buffer = tex->bo; - if (stride) - *stride = tex->pitch * tex->cpp; - - return TRUE; -} - -struct pipe_texture * -brw_texture_blanket_winsys_buffer(struct pipe_screen *screen, - const struct pipe_texture *templ, - unsigned pitch, - unsigned tiling, - struct brw_winsys_buffer *buffer) +void brw_tex_init( struct brw_context *brw ) { - struct brw_screen *bscreen = brw_screen(screen); - struct brw_texture *tex; - GLuint format; - - if (templ->target != PIPE_TEXTURE_2D || - templ->last_level != 0 || - templ->depth0 != 1) - return NULL; - - if (util_format_is_compressed(templ->format)) - return NULL; - - tex = CALLOC_STRUCT(brw_texture); - if (!tex) - return NULL; - - memcpy(&tex->base, templ, sizeof *templ); - pipe_reference_init(&tex->base.reference, 1); - tex->base.screen = screen; - - /* XXX: cpp vs. blocksize - */ - tex->cpp = util_format_get_blocksize(tex->base.format); - tex->tiling = tiling; - - make_empty_list(&tex->views[0]); - make_empty_list(&tex->views[1]); - - if (!brw_texture_layout(bscreen, tex)) - goto fail; - - /* XXX Maybe some more checks? */ - if ((pitch / tex->cpp) < tex->pitch) - goto fail; - - tex->pitch = pitch / tex->cpp; - - tex->bo = buffer; - - /* fix this warning */ -#if 0 - if (tex->size > buffer->size) - goto fail; -#endif - - tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - tex->ss.ss0.surface_type = translate_tex_target(tex->base.target); - - format = translate_tex_format(tex->base.format); - assert(format != BRW_SURFACEFORMAT_INVALID); - tex->ss.ss0.surface_format = format; - - /* This is ok for all textures with channel width 8bit or less: - */ -/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ - - - /* XXX: what happens when tex->bo->offset changes??? - */ - tex->ss.ss1.base_addr = 0; /* reloc */ - tex->ss.ss2.mip_count = tex->base.last_level; - tex->ss.ss2.width = tex->base.width0 - 1; - tex->ss.ss2.height = tex->base.height0 - 1; - - switch (tex->tiling) { - case BRW_TILING_NONE: - tex->ss.ss3.tiled_surface = 0; - tex->ss.ss3.tile_walk = 0; - break; - case BRW_TILING_X: - tex->ss.ss3.tiled_surface = 1; - tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR; - break; - case BRW_TILING_Y: - tex->ss.ss3.tiled_surface = 1; - tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR; - break; - } - - tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1; - tex->ss.ss3.depth = tex->base.depth0 - 1; - - tex->ss.ss4.min_lod = 0; - - return &tex->base; - -fail: - FREE(tex); - return NULL; + brw->base.get_tex_transfer = brw_get_tex_transfer; + brw->base.transfer_map = brw_transfer_map; + brw->base.transfer_unmap = brw_transfer_unmap; + brw->base.tex_transfer_destroy = brw_tex_transfer_destroy; } void brw_screen_tex_init( struct brw_screen *brw_screen ) { brw_screen->base.is_format_supported = brw_is_format_supported; brw_screen->base.texture_create = brw_texture_create; + brw_screen->base.texture_from_handle = brw_texture_from_handle; + brw_screen->base.texture_get_handle = brw_texture_get_handle; brw_screen->base.texture_destroy = brw_texture_destroy; - brw_screen->base.texture_blanket = brw_texture_blanket; - brw_screen->base.get_tex_transfer = brw_get_tex_transfer; - brw_screen->base.transfer_map = brw_transfer_map; - brw_screen->base.transfer_unmap = brw_transfer_unmap; - brw_screen->base.tex_transfer_destroy = brw_tex_transfer_destroy; } diff --git a/src/gallium/drivers/i965/brw_structs.h b/src/gallium/drivers/i965/brw_structs.h index bf10bc04de7..e97ddeb5e1c 100644 --- a/src/gallium/drivers/i965/brw_structs.h +++ b/src/gallium/drivers/i965/brw_structs.h @@ -28,7 +28,7 @@ * Authors: * Keith Whitwell <[email protected]> */ - + #ifndef BRW_STRUCTS_H #define BRW_STRUCTS_H @@ -1149,7 +1149,7 @@ struct brw_vertex_element_state GLuint valid:1; GLuint vertex_buffer_index:5; } ve0; - + struct { GLuint dst_offset:8; diff --git a/src/gallium/drivers/i965/brw_winsys.h b/src/gallium/drivers/i965/brw_winsys.h index c82d00f4a47..f30c7f18132 100644 --- a/src/gallium/drivers/i965/brw_winsys.h +++ b/src/gallium/drivers/i965/brw_winsys.h @@ -162,6 +162,16 @@ struct brw_winsys_screen { unsigned alignment, struct brw_winsys_buffer **bo_out); + enum pipe_error (*bo_from_handle)(struct brw_winsys_screen *sws, + struct winsys_handle *whandle, + unsigned *stride, + unsigned *tiling, + struct brw_winsys_buffer **bo_out); + + enum pipe_error (*bo_get_handle)(struct brw_winsys_buffer *buffer, + struct winsys_handle *whandle, + unsigned stride); + /* Destroy a buffer when our refcount goes to zero: */ void (*bo_destroy)(struct brw_winsys_buffer *buffer); @@ -257,28 +267,6 @@ bo_reference(struct brw_winsys_buffer **ptr, struct brw_winsys_buffer *buf) struct pipe_screen *brw_create_screen(struct brw_winsys_screen *iws, unsigned pci_id); -/** - * Get the brw_winsys buffer backing the texture. - * - * TODO UGLY - */ -struct pipe_texture; -boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture, - struct brw_winsys_buffer **buffer, - unsigned *stride); - -/** - * Wrap a brw_winsys buffer with a texture blanket. - * - * TODO UGLY - */ -struct pipe_texture * -brw_texture_blanket_winsys_buffer(struct pipe_screen *screen, - const struct pipe_texture *template, - unsigned pitch, - unsigned tiling, - struct brw_winsys_buffer *buffer); - /************************************************************************* * Cooperative dumping between winsys and driver. TODO: make this diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 8248b2a4132..26770d6b1e9 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -377,6 +377,42 @@ identity_delete_vs_state(struct pipe_context *_pipe, vs); } + +static void * +identity_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *vertex_elements) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_vertex_elements_state(pipe, + num_elements, + vertex_elements); +} + +static void +identity_bind_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_vertex_elements_state(pipe, + velems); +} + +static void +identity_delete_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_vertex_elements_state(pipe, + velems); +} + static void identity_set_blend_color(struct pipe_context *_pipe, const struct pipe_blend_color *blend_color) @@ -563,20 +599,6 @@ identity_set_vertex_buffers(struct pipe_context *_pipe, num_buffers, buffers); } - -static void -identity_set_vertex_elements(struct pipe_context *_pipe, - unsigned num_elements, - const struct pipe_vertex_element *vertex_elements) -{ - struct identity_context *id_pipe = identity_context(_pipe); - struct pipe_context *pipe = id_pipe->pipe; - - pipe->set_vertex_elements(pipe, - num_elements, - vertex_elements); -} - static void identity_surface_copy(struct pipe_context *_pipe, struct pipe_surface *_dst, @@ -689,6 +711,76 @@ identity_is_buffer_referenced(struct pipe_context *_pipe, buffer); } + + +static struct pipe_transfer * +identity_context_get_tex_transfer(struct pipe_context *_context, + struct pipe_texture *_texture, + unsigned face, + unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, + unsigned y, + unsigned w, + unsigned h) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_context *context = id_context->pipe; + struct pipe_texture *texture = id_texture->texture; + struct pipe_transfer *result; + + result = context->get_tex_transfer(context, + texture, + face, + level, + zslice, + usage, + x, + y, + w, + h); + + if (result) + return identity_transfer_create(id_context, id_texture, result); + return NULL; +} + +static void +identity_context_tex_transfer_destroy(struct pipe_context *_pipe, + struct pipe_transfer *_transfer) +{ + identity_transfer_destroy(identity_context(_pipe), + identity_transfer(_transfer)); +} + +static void * +identity_context_transfer_map(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_transfer *id_transfer = identity_transfer(_transfer); + struct pipe_context *context = id_context->pipe; + struct pipe_transfer *transfer = id_transfer->transfer; + + return context->transfer_map(context, + transfer); +} + +static void +identity_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct identity_context *id_context = identity_context(_context); + struct identity_transfer *id_transfer = identity_transfer(_transfer); + struct pipe_context *context = id_context->pipe; + struct pipe_transfer *transfer = id_transfer->transfer; + + context->transfer_unmap(context, + transfer); +} + struct pipe_context * identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) { @@ -733,6 +825,9 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.create_vs_state = identity_create_vs_state; id_pipe->base.bind_vs_state = identity_bind_vs_state; id_pipe->base.delete_vs_state = identity_delete_vs_state; + id_pipe->base.create_vertex_elements_state = identity_create_vertex_elements_state; + id_pipe->base.bind_vertex_elements_state = identity_bind_vertex_elements_state; + id_pipe->base.delete_vertex_elements_state = identity_delete_vertex_elements_state; id_pipe->base.set_blend_color = identity_set_blend_color; id_pipe->base.set_stencil_ref = identity_set_stencil_ref; id_pipe->base.set_clip_state = identity_set_clip_state; @@ -744,13 +839,16 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.set_fragment_sampler_textures = identity_set_fragment_sampler_textures; id_pipe->base.set_vertex_sampler_textures = identity_set_vertex_sampler_textures; id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers; - id_pipe->base.set_vertex_elements = identity_set_vertex_elements; id_pipe->base.surface_copy = identity_surface_copy; id_pipe->base.surface_fill = identity_surface_fill; id_pipe->base.clear = identity_clear; id_pipe->base.flush = identity_flush; id_pipe->base.is_texture_referenced = identity_is_texture_referenced; id_pipe->base.is_buffer_referenced = identity_is_buffer_referenced; + id_pipe->base.get_tex_transfer = identity_context_get_tex_transfer; + id_pipe->base.tex_transfer_destroy = identity_context_tex_transfer_destroy; + id_pipe->base.transfer_map = identity_context_transfer_map; + id_pipe->base.transfer_unmap = identity_context_transfer_unmap; id_pipe->pipe = pipe; diff --git a/src/gallium/drivers/identity/id_drm.c b/src/gallium/drivers/identity/id_drm.c index f258c38cd71..936ccc444a8 100644 --- a/src/gallium/drivers/identity/id_drm.c +++ b/src/gallium/drivers/identity/id_drm.c @@ -63,62 +63,6 @@ identity_drm_create_screen(struct drm_api *_api, int fd, return identity_screen_create(screen); } - -static struct pipe_texture * -identity_drm_texture_from_shared_handle(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *templ, - const char *name, - unsigned stride, - unsigned handle) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_drm_api *id_api = identity_drm_api(_api); - struct pipe_screen *screen = id_screen->screen; - struct drm_api *api = id_api->api; - struct pipe_texture *result; - - result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle); - - result = identity_texture_create(identity_screen(_screen), result); - - return result; -} - -static boolean -identity_drm_shared_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_texture *id_texture = identity_texture(_texture); - struct identity_drm_api *id_api = identity_drm_api(_api); - struct pipe_screen *screen = id_screen->screen; - struct pipe_texture *texture = id_texture->texture; - struct drm_api *api = id_api->api; - - return api->shared_handle_from_texture(api, screen, texture, stride, handle); -} - -static boolean -identity_drm_local_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_texture *id_texture = identity_texture(_texture); - struct identity_drm_api *id_api = identity_drm_api(_api); - struct pipe_screen *screen = id_screen->screen; - struct pipe_texture *texture = id_texture->texture; - struct drm_api *api = id_api->api; - - return api->local_handle_from_texture(api, screen, texture, stride, handle); -} - static void identity_drm_destroy(struct drm_api *_api) { @@ -145,9 +89,6 @@ identity_drm_create(struct drm_api *api) id_api->base.name = api->name; id_api->base.driver_name = api->driver_name; id_api->base.create_screen = identity_drm_create_screen; - id_api->base.texture_from_shared_handle = identity_drm_texture_from_shared_handle; - id_api->base.shared_handle_from_texture = identity_drm_shared_handle_from_texture; - id_api->base.local_handle_from_texture = identity_drm_local_handle_from_texture; id_api->base.destroy = identity_drm_destroy; id_api->api = api; diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c index 2b1a60c1bf1..d37fb0042e5 100644 --- a/src/gallium/drivers/identity/id_objects.c +++ b/src/gallium/drivers/identity/id_objects.c @@ -30,6 +30,7 @@ #include "id_screen.h" #include "id_objects.h" +#include "id_context.h" struct pipe_buffer * identity_buffer_create(struct identity_screen *id_screen, @@ -142,7 +143,8 @@ identity_surface_destroy(struct identity_surface *id_surface) struct pipe_transfer * -identity_transfer_create(struct identity_texture *id_texture, +identity_transfer_create(struct identity_context *id_context, + struct identity_texture *id_texture, struct pipe_transfer *transfer) { struct identity_transfer *id_transfer; @@ -159,25 +161,25 @@ identity_transfer_create(struct identity_texture *id_texture, memcpy(&id_transfer->base, transfer, sizeof(struct pipe_transfer)); id_transfer->base.texture = NULL; - pipe_texture_reference(&id_transfer->base.texture, &id_texture->base); id_transfer->transfer = transfer; + + pipe_texture_reference(&id_transfer->base.texture, &id_texture->base); assert(id_transfer->base.texture == &id_texture->base); return &id_transfer->base; error: - transfer->texture->screen->tex_transfer_destroy(transfer); + id_context->pipe->tex_transfer_destroy(id_context->pipe, transfer); return NULL; } void -identity_transfer_destroy(struct identity_transfer *id_transfer) +identity_transfer_destroy(struct identity_context *id_context, + struct identity_transfer *id_transfer) { - struct identity_screen *id_screen = identity_screen(id_transfer->base.texture->screen); - struct pipe_screen *screen = id_screen->screen; - pipe_texture_reference(&id_transfer->base.texture, NULL); - screen->tex_transfer_destroy(id_transfer->transfer); + id_context->pipe->tex_transfer_destroy(id_context->pipe, + id_transfer->transfer); FREE(id_transfer); } diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h index 77cc7190798..7333ecfb7fb 100644 --- a/src/gallium/drivers/identity/id_objects.h +++ b/src/gallium/drivers/identity/id_objects.h @@ -35,6 +35,7 @@ #include "id_screen.h" +struct identity_context; struct identity_buffer { @@ -64,6 +65,7 @@ struct identity_transfer { struct pipe_transfer base; + struct pipe_context *pipe; struct pipe_transfer *transfer; }; @@ -177,11 +179,13 @@ void identity_surface_destroy(struct identity_surface *id_surface); struct pipe_transfer * -identity_transfer_create(struct identity_texture *id_texture, +identity_transfer_create(struct identity_context *id_context, + struct identity_texture *id_texture, struct pipe_transfer *transfer); void -identity_transfer_destroy(struct identity_transfer *id_transfer); +identity_transfer_destroy(struct identity_context *id_context, + struct identity_transfer *id_transfer); struct pipe_video_surface * identity_video_surface_create(struct identity_screen *id_screen, diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c index b85492114a3..419b1465787 100644 --- a/src/gallium/drivers/identity/id_screen.c +++ b/src/gallium/drivers/identity/id_screen.c @@ -135,27 +135,40 @@ identity_screen_texture_create(struct pipe_screen *_screen, } static struct pipe_texture * -identity_screen_texture_blanket(struct pipe_screen *_screen, - const struct pipe_texture *templat, - const unsigned *stride, - struct pipe_buffer *_buffer) +identity_screen_texture_from_handle(struct pipe_screen *_screen, + const struct pipe_texture *templ, + struct winsys_handle *handle) { struct identity_screen *id_screen = identity_screen(_screen); - struct identity_buffer *id_buffer = identity_buffer(_buffer); struct pipe_screen *screen = id_screen->screen; - struct pipe_buffer *buffer = id_buffer->buffer; struct pipe_texture *result; - result = screen->texture_blanket(screen, - templat, - stride, - buffer); + /* TODO trace call */ - if (result) - return identity_texture_create(id_screen, result); - return NULL; + result = screen->texture_from_handle(screen, templ, handle); + + result = identity_texture_create(identity_screen(_screen), result); + + return result; } +static boolean +identity_screen_texture_get_handle(struct pipe_screen *_screen, + struct pipe_texture *_texture, + struct winsys_handle *handle) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_screen *screen = id_screen->screen; + struct pipe_texture *texture = id_texture->texture; + + /* TODO trace call */ + + return screen->texture_get_handle(screen, texture, handle); +} + + + static void identity_screen_texture_destroy(struct pipe_texture *_texture) { @@ -194,71 +207,6 @@ identity_screen_tex_surface_destroy(struct pipe_surface *_surface) identity_surface_destroy(identity_surface(_surface)); } -static struct pipe_transfer * -identity_screen_get_tex_transfer(struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned face, - unsigned level, - unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, - unsigned y, - unsigned w, - unsigned h) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_texture *id_texture = identity_texture(_texture); - struct pipe_screen *screen = id_screen->screen; - struct pipe_texture *texture = id_texture->texture; - struct pipe_transfer *result; - - result = screen->get_tex_transfer(screen, - texture, - face, - level, - zslice, - usage, - x, - y, - w, - h); - - if (result) - return identity_transfer_create(id_texture, result); - return NULL; -} - -static void -identity_screen_tex_transfer_destroy(struct pipe_transfer *_transfer) -{ - identity_transfer_destroy(identity_transfer(_transfer)); -} - -static void * -identity_screen_transfer_map(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_transfer *id_transfer = identity_transfer(_transfer); - struct pipe_screen *screen = id_screen->screen; - struct pipe_transfer *transfer = id_transfer->transfer; - - return screen->transfer_map(screen, - transfer); -} - -static void -identity_screen_transfer_unmap(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct identity_transfer *id_transfer = identity_transfer(_transfer); - struct pipe_screen *screen = id_screen->screen; - struct pipe_transfer *transfer = id_transfer->transfer; - - screen->transfer_unmap(screen, - transfer); -} static struct pipe_buffer * identity_screen_buffer_create(struct pipe_screen *_screen, @@ -298,31 +246,6 @@ identity_screen_user_buffer_create(struct pipe_screen *_screen, return NULL; } -static struct pipe_buffer * -identity_screen_surface_buffer_create(struct pipe_screen *_screen, - unsigned width, - unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - struct identity_screen *id_screen = identity_screen(_screen); - struct pipe_screen *screen = id_screen->screen; - struct pipe_buffer *result; - - result = screen->surface_buffer_create(screen, - width, - height, - format, - usage, - tex_usage, - stride); - - if (result) - return identity_buffer_create(id_screen, result); - return NULL; -} static void * identity_screen_buffer_map(struct pipe_screen *_screen, @@ -495,17 +418,13 @@ identity_screen_create(struct pipe_screen *screen) id_screen->base.is_format_supported = identity_screen_is_format_supported; id_screen->base.context_create = identity_screen_context_create; id_screen->base.texture_create = identity_screen_texture_create; - id_screen->base.texture_blanket = identity_screen_texture_blanket; + id_screen->base.texture_from_handle = identity_screen_texture_from_handle; + id_screen->base.texture_get_handle = identity_screen_texture_get_handle; id_screen->base.texture_destroy = identity_screen_texture_destroy; id_screen->base.get_tex_surface = identity_screen_get_tex_surface; id_screen->base.tex_surface_destroy = identity_screen_tex_surface_destroy; - id_screen->base.get_tex_transfer = identity_screen_get_tex_transfer; - id_screen->base.tex_transfer_destroy = identity_screen_tex_transfer_destroy; - id_screen->base.transfer_map = identity_screen_transfer_map; - id_screen->base.transfer_unmap = identity_screen_transfer_unmap; id_screen->base.buffer_create = identity_screen_buffer_create; id_screen->base.user_buffer_create = identity_screen_user_buffer_create; - id_screen->base.surface_buffer_create = identity_screen_surface_buffer_create; if (screen->buffer_map) id_screen->base.buffer_map = identity_screen_buffer_map; if (screen->buffer_map_range) diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 41ac1cee72d..89c06ea3ad7 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -55,7 +55,7 @@ testprogs := lp_test_format \ LIBS += $(GL_LIB_DEPS) -L. -lllvmpipe -L../../auxiliary/ -lgallium -$(testprogs): lp_test_% : lp_test_%.o lp_test_main.o libllvmpipe.a - $(LD) $(filter %.o,$^) -o $@ -Wl,--start-group $(LIBS) -Wl,--end-group +#$(testprogs): lp_test_% : lp_test_%.o lp_test_main.o libllvmpipe.a +# $(LD) $(filter %.o,$^) -o $@ -Wl,--start-group $(LIBS) -Wl,--end-group -default: $(testprogs) +#default: $(testprogs) diff --git a/src/gallium/drivers/llvmpipe/lp_buffer.c b/src/gallium/drivers/llvmpipe/lp_buffer.c index 9eda9720818..6e0f37393e9 100644 --- a/src/gallium/drivers/llvmpipe/lp_buffer.c +++ b/src/gallium/drivers/llvmpipe/lp_buffer.c @@ -30,7 +30,6 @@ #include "util/u_memory.h" #include "util/u_math.h" -#include "lp_winsys.h" #include "lp_screen.h" #include "lp_buffer.h" diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index e31ae6a3fc1..945e3e05588 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -145,6 +145,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe->pipe.bind_vs_state = llvmpipe_bind_vs_state; llvmpipe->pipe.delete_vs_state = llvmpipe_delete_vs_state; + llvmpipe->pipe.create_vertex_elements_state = llvmpipe_create_vertex_elements_state; + llvmpipe->pipe.bind_vertex_elements_state = llvmpipe_bind_vertex_elements_state; + llvmpipe->pipe.delete_vertex_elements_state = llvmpipe_delete_vertex_elements_state; + llvmpipe->pipe.set_blend_color = llvmpipe_set_blend_color; llvmpipe->pipe.set_stencil_ref = llvmpipe_set_stencil_ref; llvmpipe->pipe.set_clip_state = llvmpipe_set_clip_state; @@ -157,7 +161,6 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe->pipe.set_viewport_state = llvmpipe_set_viewport_state; llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers; - llvmpipe->pipe.set_vertex_elements = llvmpipe_set_vertex_elements; llvmpipe->pipe.draw_arrays = llvmpipe_draw_arrays; llvmpipe->pipe.draw_elements = llvmpipe_draw_elements; @@ -170,6 +173,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe->pipe.is_buffer_referenced = llvmpipe_is_buffer_referenced; llvmpipe_init_query_funcs( llvmpipe ); + llvmpipe_init_context_texture_funcs( &llvmpipe->pipe ); /* * Create drawing context and plug our rendering stage into it. diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 955c7eb8e0e..217ec59b688 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -46,6 +46,7 @@ struct lp_fragment_shader; struct lp_vertex_shader; struct lp_blend_state; struct setup_context; +struct lp_velems_state; struct llvmpipe_context { struct pipe_context pipe; /**< base class */ @@ -58,6 +59,7 @@ struct llvmpipe_context { const struct pipe_rasterizer_state *rasterizer; struct lp_fragment_shader *fs; const struct lp_vertex_shader *vs; + const struct lp_velems_state *velems; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -71,13 +73,11 @@ struct llvmpipe_context { struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; unsigned num_samplers; unsigned num_textures; unsigned num_vertex_samplers; unsigned num_vertex_textures; - unsigned num_vertex_elements; unsigned num_vertex_buffers; unsigned dirty; /**< Mask of LP_NEW_x flags */ diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index bf832433be1..1b4e8899359 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -79,12 +79,12 @@ llvmpipe_flush( struct pipe_context *pipe, for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no); - debug_dump_surface(filename, llvmpipe->framebuffer.cbufs[i]); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[0]); } if (0) { util_snprintf(filename, sizeof(filename), "zsbuf_%u", frame_no); - debug_dump_surface(filename, llvmpipe->framebuffer.zsbuf); + debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.zsbuf); } ++frame_no; diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index bacff500d63..5887613120d 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -57,8 +57,11 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) elem_types[LP_JIT_TEXTURE_HEIGHT] = LLVMInt32Type(); elem_types[LP_JIT_TEXTURE_DEPTH] = LLVMInt32Type(); elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_STRIDE] = LLVMInt32Type(); - elem_types[LP_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0); + elem_types[LP_JIT_TEXTURE_ROW_STRIDE] = + LLVMArrayType(LLVMInt32Type(), LP_MAX_TEXTURE_2D_LEVELS); + elem_types[LP_JIT_TEXTURE_DATA] = + LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0), + LP_MAX_TEXTURE_2D_LEVELS); texture_type = LLVMStructType(elem_types, Elements(elem_types), 0); @@ -74,9 +77,9 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, last_level, screen->target, texture_type, LP_JIT_TEXTURE_LAST_LEVEL); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, stride, + LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, row_stride, screen->target, texture_type, - LP_JIT_TEXTURE_STRIDE); + LP_JIT_TEXTURE_ROW_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, data, screen->target, texture_type, LP_JIT_TEXTURE_DATA); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 0ebb2826fa2..13167ae3bf4 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -39,6 +39,7 @@ #include "gallivm/lp_bld_struct.h" #include "pipe/p_state.h" +#include "lp_texture.h" struct llvmpipe_screen; @@ -50,8 +51,8 @@ struct lp_jit_texture uint32_t height; uint32_t depth; uint32_t last_level; - uint32_t stride; - const void *data; + uint32_t row_stride[LP_MAX_TEXTURE_2D_LEVELS]; + const void *data[LP_MAX_TEXTURE_2D_LEVELS]; }; @@ -60,7 +61,7 @@ enum { LP_JIT_TEXTURE_HEIGHT, LP_JIT_TEXTURE_DEPTH, LP_JIT_TEXTURE_LAST_LEVEL, - LP_JIT_TEXTURE_STRIDE, + LP_JIT_TEXTURE_ROW_STRIDE, LP_JIT_TEXTURE_DATA }; diff --git a/src/gallium/drivers/llvmpipe/lp_public.h b/src/gallium/drivers/llvmpipe/lp_public.h new file mode 100644 index 00000000000..ec6b660b48e --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_public.h @@ -0,0 +1,10 @@ +#ifndef LP_PUBLIC_H +#define LP_PUBLIC_H + +struct pipe_screen; +struct sw_winsys; + +struct pipe_screen * +llvmpipe_create_screen(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 72492c0f0ca..505cb21503a 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -397,7 +397,7 @@ end: static boolean lp_scene_map_buffers( struct lp_scene *scene ) { - struct pipe_screen *screen = scene->pipe->screen; + struct pipe_context *pipe = scene->pipe; struct pipe_surface *cbuf, *zsbuf; int i; @@ -409,7 +409,7 @@ lp_scene_map_buffers( struct lp_scene *scene ) for (i = 0; i < scene->fb.nr_cbufs; i++) { cbuf = scene->fb.cbufs[i]; if (cbuf) { - scene->cbuf_transfer[i] = screen->get_tex_transfer(screen, + scene->cbuf_transfer[i] = pipe->get_tex_transfer(pipe, cbuf->texture, cbuf->face, cbuf->level, @@ -421,7 +421,7 @@ lp_scene_map_buffers( struct lp_scene *scene ) if (!scene->cbuf_transfer[i]) goto fail; - scene->cbuf_map[i] = screen->transfer_map(screen, + scene->cbuf_map[i] = pipe->transfer_map(pipe, scene->cbuf_transfer[i]); if (!scene->cbuf_map[i]) goto fail; @@ -432,7 +432,7 @@ lp_scene_map_buffers( struct lp_scene *scene ) */ zsbuf = scene->fb.zsbuf; if (zsbuf) { - scene->zsbuf_transfer = screen->get_tex_transfer(screen, + scene->zsbuf_transfer = pipe->get_tex_transfer(pipe, zsbuf->texture, zsbuf->face, zsbuf->level, @@ -444,7 +444,7 @@ lp_scene_map_buffers( struct lp_scene *scene ) if (!scene->zsbuf_transfer) goto fail; - scene->zsbuf_map = screen->transfer_map(screen, + scene->zsbuf_map = pipe->transfer_map(pipe, scene->zsbuf_transfer); if (!scene->zsbuf_map) goto fail; @@ -469,25 +469,25 @@ fail: static void lp_scene_unmap_buffers( struct lp_scene *scene ) { - struct pipe_screen *screen = scene->pipe->screen; + struct pipe_context *pipe = scene->pipe; unsigned i; for (i = 0; i < scene->fb.nr_cbufs; i++) { if (scene->cbuf_map[i]) - screen->transfer_unmap(screen, scene->cbuf_transfer[i]); + pipe->transfer_unmap(pipe, scene->cbuf_transfer[i]); if (scene->cbuf_transfer[i]) - screen->tex_transfer_destroy(scene->cbuf_transfer[i]); + pipe->tex_transfer_destroy(pipe, scene->cbuf_transfer[i]); scene->cbuf_transfer[i] = NULL; scene->cbuf_map[i] = NULL; } if (scene->zsbuf_map) - screen->transfer_unmap(screen, scene->zsbuf_transfer); + pipe->transfer_unmap(pipe, scene->zsbuf_transfer); if (scene->zsbuf_transfer) - screen->tex_transfer_destroy(scene->zsbuf_transfer); + pipe->tex_transfer_destroy(pipe, scene->zsbuf_transfer); scene->zsbuf_transfer = NULL; scene->zsbuf_map = NULL; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index f84ede675b3..5093f58bb19 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -34,11 +34,13 @@ #include "lp_texture.h" #include "lp_buffer.h" #include "lp_fence.h" -#include "lp_winsys.h" #include "lp_jit.h" #include "lp_screen.h" #include "lp_context.h" #include "lp_debug.h" +#include "lp_public.h" + +#include "state_tracker/sw_winsys.h" #ifdef DEBUG int LP_DEBUG = 0; @@ -107,11 +109,11 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 13; /* max 4Kx4K */ + return LP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 9; /* max 256x256x256 */ + return LP_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 13; /* max 4Kx4K */ + return LP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: @@ -167,7 +169,7 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, unsigned geom_flags ) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; const struct util_format_description *format_desc; format_desc = util_format_description(format); @@ -238,18 +240,6 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, } -static struct pipe_buffer * -llvmpipe_surface_buffer_create(struct pipe_screen *screen, - unsigned width, unsigned height, - enum pipe_format format, - unsigned tex_usage, - unsigned usage, - unsigned *stride) -{ - /* This function should never be used */ - assert(0); - return NULL; -} static void @@ -258,7 +248,7 @@ llvmpipe_flush_frontbuffer(struct pipe_screen *_screen, void *context_private) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; struct llvmpipe_texture *texture = llvmpipe_texture(surface->texture); assert(texture->dt); @@ -271,7 +261,7 @@ static void llvmpipe_destroy_screen( struct pipe_screen *_screen ) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; lp_jit_screen_cleanup(screen); @@ -288,7 +278,7 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen ) * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen). */ struct pipe_screen * -llvmpipe_create_screen(struct llvmpipe_winsys *winsys) +llvmpipe_create_screen(struct sw_winsys *winsys) { struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen); @@ -309,7 +299,6 @@ llvmpipe_create_screen(struct llvmpipe_winsys *winsys) screen->base.get_paramf = llvmpipe_get_paramf; screen->base.is_format_supported = llvmpipe_is_format_supported; - screen->base.surface_buffer_create = llvmpipe_surface_buffer_create; screen->base.context_create = llvmpipe_create_context; screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h index 4a1b4d6f3e2..d977f98cfaa 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.h +++ b/src/gallium/drivers/llvmpipe/lp_screen.h @@ -34,23 +34,21 @@ #ifndef LP_SCREEN_H #define LP_SCREEN_H -#include <llvm-c/Core.h> -#include <llvm-c/Analysis.h> -#include <llvm-c/Target.h> +#include "os/os_llvm.h" #include <llvm-c/ExecutionEngine.h> #include "pipe/p_screen.h" #include "pipe/p_defines.h" -struct llvmpipe_winsys; +struct sw_winsys; struct llvmpipe_screen { struct pipe_screen base; - struct llvmpipe_winsys *winsys; + struct sw_winsys *winsys; LLVMModuleRef module; LLVMExecutionEngineRef engine; @@ -76,4 +74,5 @@ llvmpipe_screen( struct pipe_screen *pipe ) } + #endif /* LP_SCREEN_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index b0713c3b71d..c870f89d01d 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -46,7 +46,7 @@ #include "lp_rast.h" #include "lp_setup_context.h" #include "lp_screen.h" -#include "lp_winsys.h" +#include "state_tracker/sw_winsys.h" #include "draw/draw_context.h" #include "draw/draw_vbuf.h" @@ -471,20 +471,27 @@ lp_setup_set_sampler_textures( struct setup_context *setup, jit_tex->height = tex->height0; jit_tex->depth = tex->depth0; jit_tex->last_level = tex->last_level; - jit_tex->stride = lp_tex->stride[0]; - if(!lp_tex->dt) { - jit_tex->data = lp_tex->data; + if (!lp_tex->dt) { + /* regular texture - setup array of mipmap level pointers */ + int j; + for (j = 0; j <= tex->last_level; j++) { + jit_tex->data[j] = + (ubyte *) lp_tex->data + lp_tex->level_offset[j]; + jit_tex->row_stride[j] = lp_tex->stride[j]; + } } else { + /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); - struct llvmpipe_winsys *winsys = screen->winsys; - jit_tex->data = winsys->displaytarget_map(winsys, lp_tex->dt, + struct sw_winsys *winsys = screen->winsys; + jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_BUFFER_USAGE_CPU_READ); - assert(jit_tex->data); + jit_tex->row_stride[0] = lp_tex->stride[0]; + assert(jit_tex->data[0]); } /* the scene references this texture */ diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c index 24291da91e4..671e74465c0 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -231,57 +231,29 @@ lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_QUAD_STRIP: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride)); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; @@ -415,57 +387,28 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - setup->triangle( setup, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_QUAD_STRIP: - if (setup->flatshade_first) { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - setup->triangle( setup, - - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - setup->triangle( setup, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - setup->triangle( setup, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 9beba32271f..a5a1a720742 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -31,7 +31,7 @@ #ifndef LP_STATE_H #define LP_STATE_H -#include <llvm-c/Core.h> +#include "os/os_llvm.h" #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" @@ -119,6 +119,10 @@ struct lp_vertex_shader { struct draw_vertex_shader *draw_data; }; +struct lp_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; void * @@ -176,8 +180,14 @@ void *llvmpipe_create_vs_state(struct pipe_context *, void llvmpipe_bind_vs_state(struct pipe_context *, void *); void llvmpipe_delete_vs_state(struct pipe_context *, void *); +void *llvmpipe_create_vertex_elements_state(struct pipe_context *, + unsigned count, + const struct pipe_vertex_element *); +void llvmpipe_bind_vertex_elements_state(struct pipe_context *, void *); +void llvmpipe_delete_vertex_elements_state(struct pipe_context *, void *); + void llvmpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); + const struct pipe_poly_stipple * ); void llvmpipe_set_scissor_state( struct pipe_context *, const struct pipe_scissor_state * ); @@ -194,10 +204,6 @@ llvmpipe_set_vertex_sampler_textures(struct pipe_context *, void llvmpipe_set_viewport_state( struct pipe_context *, const struct pipe_viewport_state * ); -void llvmpipe_set_vertex_elements(struct pipe_context *, - unsigned count, - const struct pipe_vertex_element *); - void llvmpipe_set_vertex_buffers(struct pipe_context *, unsigned count, const struct pipe_vertex_buffer *); diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index c4b79dd4156..9a8de0edfda 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -40,7 +40,7 @@ * - depth/stencil test (stencil TBI) * - blending * - * This file has only the glue to assembly the fragment pipeline. The actual + * This file has only the glue to assemble the fragment pipeline. The actual * plumbing of converting Gallium state into LLVM IR is done elsewhere, in the * lp_bld_*.[ch] files, and in a complete generic and reusable way. Here we * muster the LLVM JIT execution engine to create a function that follows an @@ -95,6 +95,9 @@ #include "lp_tex_sample.h" +#include <llvm-c/Analysis.h> + + static const unsigned char quad_offset_x[4] = {0, 1, 0, 1}; static const unsigned char quad_offset_y[4] = {0, 0, 1, 1}; diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index 57ac25ea0cb..f6427aa908e 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -35,24 +35,41 @@ #include "draw/draw_context.h" +void * +llvmpipe_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) +{ + struct lp_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct lp_velems_state *) MALLOC(sizeof(struct lp_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + void -llvmpipe_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *attribs) +llvmpipe_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); + struct lp_velems_state *lp_velems = (struct lp_velems_state *) velems; - assert(count <= PIPE_MAX_ATTRIBS); - - memcpy(llvmpipe->vertex_element, attribs, - count * sizeof(struct pipe_vertex_element)); - llvmpipe->num_vertex_elements = count; + llvmpipe->velems = lp_velems; llvmpipe->dirty |= LP_NEW_VERTEX; - draw_set_vertex_elements(llvmpipe->draw, count, attribs); + if (velems) + draw_set_vertex_elements(llvmpipe->draw, lp_velems->count, lp_velems->velem); } +void +llvmpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} void llvmpipe_set_vertex_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h index a9b99945f92..1df98978988 100644 --- a/src/gallium/drivers/llvmpipe/lp_test.h +++ b/src/gallium/drivers/llvmpipe/lp_test.h @@ -41,7 +41,7 @@ #include <stdio.h> #include <float.h> -#include <llvm-c/Core.h> +#include "os/os_llvm.h" #include <llvm-c/Analysis.h> #include <llvm-c/ExecutionEngine.h> #include <llvm-c/Target.h> diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index d05157991bb..2c4d7fb6e14 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -29,7 +29,7 @@ #include <stdlib.h> #include <stdio.h> -#include <llvm-c/Core.h> +#include "os/os_llvm.h" #include <llvm-c/Analysis.h> #include <llvm-c/ExecutionEngine.h> #include <llvm-c/Target.h> diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.h b/src/gallium/drivers/llvmpipe/lp_tex_sample.h index cb59a94464a..799df182b6a 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.h +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.h @@ -29,7 +29,7 @@ #define LP_TEX_SAMPLE_H -#include <llvm-c/Core.h> +#include "os/os_llvm.h" struct lp_sampler_static_state; diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c index 632462460a3..662508af61a 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c @@ -51,10 +51,11 @@ /** - * This provides the bridge between the sampler state store in lp_jit_context - * and lp_jit_texture and the sampler code generator. It provides the - * texture layout information required by the texture sampler code generator - * in terms of the state stored in lp_jit_context and lp_jit_texture in runtime. + * This provides the bridge between the sampler state store in + * lp_jit_context and lp_jit_texture and the sampler code + * generator. It provides the texture layout information required by + * the texture sampler code generator in terms of the state stored in + * lp_jit_context and lp_jit_texture in runtime. */ struct llvmpipe_sampler_dynamic_state { @@ -79,6 +80,9 @@ struct lp_llvm_sampler_soa /** * Fetch the specified member of the lp_jit_texture structure. + * \param emit_load if TRUE, emit the LLVM load instruction to actually + * fetch the field's value. Otherwise, just emit the + * GEP code to address the field. * * @sa http://llvm.org/docs/GetElementPtr.html */ @@ -87,9 +91,11 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, LLVMBuilderRef builder, unsigned unit, unsigned member_index, - const char *member_name) + const char *member_name, + boolean emit_load) { - struct llvmpipe_sampler_dynamic_state *state = (struct llvmpipe_sampler_dynamic_state *)base; + struct llvmpipe_sampler_dynamic_state *state = + (struct llvmpipe_sampler_dynamic_state *)base; LLVMValueRef indices[4]; LLVMValueRef ptr; LLVMValueRef res; @@ -107,7 +113,10 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), ""); - res = LLVMBuildLoad(builder, ptr, ""); + if (emit_load) + res = LLVMBuildLoad(builder, ptr, ""); + else + res = ptr; lp_build_name(res, "context.texture%u.%s", unit, member_name); @@ -116,28 +125,30 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, /** - * Helper macro to instantiate the functions that generate the code to fetch - * the members of lp_jit_texture to fulfill the sampler code generator requests. + * Helper macro to instantiate the functions that generate the code to + * fetch the members of lp_jit_texture to fulfill the sampler code + * generator requests. * - * This complexity is the price we have to pay to keep the texture sampler code - * generator a reusable module without dependencies to llvmpipe internals. + * This complexity is the price we have to pay to keep the texture + * sampler code generator a reusable module without dependencies to + * llvmpipe internals. */ -#define LP_LLVM_TEXTURE_MEMBER(_name, _index) \ +#define LP_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \ static LLVMValueRef \ lp_llvm_texture_##_name( struct lp_sampler_dynamic_state *base, \ LLVMBuilderRef builder, \ unsigned unit) \ { \ - return lp_llvm_texture_member(base, builder, unit, _index, #_name ); \ + return lp_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \ } -LP_LLVM_TEXTURE_MEMBER(width, LP_JIT_TEXTURE_WIDTH) -LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT) -LP_LLVM_TEXTURE_MEMBER(depth, LP_JIT_TEXTURE_DEPTH) -LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL) -LP_LLVM_TEXTURE_MEMBER(stride, LP_JIT_TEXTURE_STRIDE) -LP_LLVM_TEXTURE_MEMBER(data_ptr, LP_JIT_TEXTURE_DATA) +LP_LLVM_TEXTURE_MEMBER(width, LP_JIT_TEXTURE_WIDTH, TRUE) +LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT, TRUE) +LP_LLVM_TEXTURE_MEMBER(depth, LP_JIT_TEXTURE_DEPTH, TRUE) +LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE) +LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE) +LP_LLVM_TEXTURE_MEMBER(data_ptr, LP_JIT_TEXTURE_DATA, FALSE) static void @@ -193,7 +204,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, sampler->dynamic_state.base.height = lp_llvm_texture_height; sampler->dynamic_state.base.depth = lp_llvm_texture_depth; sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level; - sampler->dynamic_state.base.stride = lp_llvm_texture_stride; + sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride; sampler->dynamic_state.base.data_ptr = lp_llvm_texture_data_ptr; sampler->dynamic_state.static_state = static_state; sampler->dynamic_state.context_ptr = context_ptr; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 7f456355428..f2c6dbd088a 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -42,7 +42,7 @@ #include "lp_screen.h" #include "lp_texture.h" #include "lp_tile_size.h" -#include "lp_winsys.h" +#include "state_tracker/sw_winsys.h" /** @@ -93,7 +93,7 @@ static boolean llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, struct llvmpipe_texture *lpt) { - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; /* Round up the surface size to a multiple of the tile size to * avoid tile clipping. @@ -125,7 +125,8 @@ llvmpipe_texture_create(struct pipe_screen *_screen, lpt->base.screen = &screen->base; if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { if (!llvmpipe_displaytarget_layout(screen, lpt)) goto fail; } @@ -142,43 +143,6 @@ llvmpipe_texture_create(struct pipe_screen *_screen, } -static struct pipe_texture * -llvmpipe_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) -{ - /* FIXME */ -#if 0 - struct llvmpipe_texture *lpt; - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - lpt = CALLOC_STRUCT(llvmpipe_texture); - if (!lpt) - return NULL; - - lpt->base = *base; - pipe_reference_init(&lpt->base.reference, 1); - lpt->base.screen = screen; - lpt->stride[0] = stride[0]; - - pipe_buffer_reference(&lpt->buffer, buffer); - - return &lpt->base; -#else - debug_printf("llvmpipe_texture_blanket() not implemented!"); - return NULL; -#endif -} - - static void llvmpipe_texture_destroy(struct pipe_texture *pt) { @@ -187,7 +151,7 @@ llvmpipe_texture_destroy(struct pipe_texture *pt) if (lpt->dt) { /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; winsys->displaytarget_destroy(winsys, lpt->dt); } else { @@ -279,7 +243,7 @@ llvmpipe_tex_surface_destroy(struct pipe_surface *surf) static struct pipe_transfer * -llvmpipe_get_tex_transfer(struct pipe_screen *screen, +llvmpipe_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -330,7 +294,8 @@ llvmpipe_get_tex_transfer(struct pipe_screen *screen, static void -llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer) +llvmpipe_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is @@ -343,10 +308,10 @@ llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer) static void * -llvmpipe_transfer_map( struct pipe_screen *_screen, +llvmpipe_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { - struct llvmpipe_screen *screen = llvmpipe_screen(_screen); + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); ubyte *map, *xfer_map; struct llvmpipe_texture *lpt; enum pipe_format format; @@ -357,7 +322,7 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, if (lpt->dt) { /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; map = winsys->displaytarget_map(winsys, lpt->dt, pipe_transfer_buffer_flags(transfer)); @@ -387,10 +352,10 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, static void -llvmpipe_transfer_unmap(struct pipe_screen *screen, - struct pipe_transfer *transfer) +llvmpipe_transfer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) { - struct llvmpipe_screen *lp_screen = llvmpipe_screen(screen); + struct llvmpipe_screen *lp_screen = llvmpipe_screen(pipe->screen); struct llvmpipe_texture *lpt; assert(transfer->texture); @@ -398,7 +363,7 @@ llvmpipe_transfer_unmap(struct pipe_screen *screen, if (lpt->dt) { /* display target */ - struct llvmpipe_winsys *winsys = lp_screen->winsys; + struct sw_winsys *winsys = lp_screen->winsys; winsys->displaytarget_unmap(winsys, lpt->dt); } } @@ -408,14 +373,18 @@ void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->texture_create = llvmpipe_texture_create; - screen->texture_blanket = llvmpipe_texture_blanket; screen->texture_destroy = llvmpipe_texture_destroy; screen->get_tex_surface = llvmpipe_get_tex_surface; screen->tex_surface_destroy = llvmpipe_tex_surface_destroy; +} + - screen->get_tex_transfer = llvmpipe_get_tex_transfer; - screen->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; - screen->transfer_map = llvmpipe_transfer_map; - screen->transfer_unmap = llvmpipe_transfer_unmap; +void +llvmpipe_init_context_texture_funcs(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = llvmpipe_get_tex_transfer; + pipe->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; + pipe->transfer_map = llvmpipe_transfer_map; + pipe->transfer_unmap = llvmpipe_transfer_unmap; } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 87c905bc027..94b667abf31 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -32,24 +32,29 @@ #include "pipe/p_state.h" +#define LP_MAX_TEXTURE_2D_LEVELS 13 /* 4K x 4K for now */ +#define LP_MAX_TEXTURE_3D_LEVELS 10 /* 512 x 512 x 512 for now */ + + struct pipe_context; struct pipe_screen; struct llvmpipe_context; -struct llvmpipe_displaytarget; + +struct sw_displaytarget; struct llvmpipe_texture { struct pipe_texture base; - unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned stride[PIPE_MAX_TEXTURE_LEVELS]; + unsigned long level_offset[LP_MAX_TEXTURE_2D_LEVELS]; + unsigned stride[LP_MAX_TEXTURE_2D_LEVELS]; /** * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET * usage. */ - struct llvmpipe_displaytarget *dt; + struct sw_displaytarget *dt; /** * Malloc'ed data for regular textures, or a mapping to dt above. @@ -93,5 +98,7 @@ llvmpipe_transfer(struct pipe_transfer *pt) extern void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen); +extern void +llvmpipe_init_context_texture_funcs(struct pipe_context *pipe); #endif /* LP_TEXTURE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_winsys.h b/src/gallium/drivers/llvmpipe/lp_winsys.h deleted file mode 100644 index ce11fa93041..00000000000 --- a/src/gallium/drivers/llvmpipe/lp_winsys.h +++ /dev/null @@ -1,125 +0,0 @@ -/************************************************************************** - * - * Copyright 2007-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 TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -/** - * @file - * llvmpipe public interface. - */ - - -#ifndef LP_WINSYS_H -#define LP_WINSYS_H - - -#include "pipe/p_compiler.h" /* for boolean */ -#include "pipe/p_format.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -struct pipe_screen; -struct pipe_context; - - -/** - * Opaque pointer. - */ -struct llvmpipe_displaytarget; - - -/** - * This is the interface that llvmpipe expects any window system - * hosting it to implement. - * - * llvmpipe is for the most part a self sufficient driver. The only thing it - * does not know is how to display a surface. - */ -struct llvmpipe_winsys -{ - void - (*destroy)( struct llvmpipe_winsys *ws ); - - boolean - (*is_displaytarget_format_supported)( struct llvmpipe_winsys *ws, - enum pipe_format format ); - - /** - * Allocate storage for a render target. - * - * Often surfaces which are meant to be blitted to the front screen (i.e., - * display targets) must be allocated with special characteristics, memory - * pools, or obtained directly from the windowing system. - * - * This callback is invoked by the pipe_screen when creating a texture marked - * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying - * storage. - */ - struct llvmpipe_displaytarget * - (*displaytarget_create)( struct llvmpipe_winsys *ws, - enum pipe_format format, - unsigned width, unsigned height, - unsigned alignment, - unsigned *stride ); - - void * - (*displaytarget_map)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - unsigned flags ); - - void - (*displaytarget_unmap)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ); - - /** - * @sa pipe_screen:flush_frontbuffer. - * - * This call will likely become asynchronous eventually. - */ - void - (*displaytarget_display)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - void *context_private ); - - void - (*displaytarget_destroy)( struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ); -}; - - - -struct pipe_screen * -llvmpipe_create_screen( struct llvmpipe_winsys * ); - - -#ifdef __cplusplus -} -#endif - -#endif /* LP_WINSYS_H */ diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index 3c2f771b51e..b1ad686022a 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -4,6 +4,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_format.h" #include <stdio.h> #include <errno.h> @@ -12,6 +13,9 @@ #include "nouveau_winsys.h" #include "nouveau_screen.h" +/* XXX this should go away */ +#include "state_tracker/drm_api.h" + static const char * nouveau_screen_get_name(struct pipe_screen *pscreen) { @@ -120,7 +124,7 @@ nouveau_screen_map_flags(unsigned pipe) if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK) flags |= NOUVEAU_BO_NOWAIT; else - if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/) + if (pipe & PIPE_BUFFER_USAGE_UNSYNCHRONIZED) flags |= NOUVEAU_BO_NOSYNC; return flags; @@ -231,6 +235,72 @@ nouveau_screen_fence_finish(struct pipe_screen *screen, return 0; } + +/* + * Both texture_{from|get}_handle use drm api defines directly which they + * shouldn't do. The problem is that from|get are pipe functions and as + * such they should be defined in the pipe level. If nouveau had a propper + * winsys interface we would have added from|get to that interface using + * the winsys_handle struct as done with other drivers. However this code + * calls directly into the libdrm_nouveau.so functions (nouveau_bo_*). So + * we need to translate the handle into something they understand. + */ +static struct pipe_texture * +nouveau_screen_texture_from_handle(struct pipe_screen *pscreen, + const struct pipe_texture *templ, + struct winsys_handle *whandle) +{ + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + struct pipe_texture *pt; + struct pipe_buffer *pb; + int ret; + + pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*)); + if (!pb) + return NULL; + + ret = nouveau_bo_handle_ref(dev, whandle->handle, (struct nouveau_bo**)(pb+1)); + if (ret) { + debug_printf("%s: ref name 0x%08x failed with %d\n", + __func__, whandle->handle, ret); + FREE(pb); + return NULL; + } + + pipe_reference_init(&pb->reference, 1); + pb->screen = pscreen; + pb->alignment = 0; + pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | + PIPE_BUFFER_USAGE_CPU_READ_WRITE; + pb->size = nouveau_bo(pb)->size; + pt = nouveau_screen(pscreen)->texture_blanket(pscreen, templ, + &whandle->stride, pb); + pipe_buffer_reference(&pb, NULL); + return pt; +} + +static boolean +nouveau_screen_texture_get_handle(struct pipe_screen *pscreen, + struct pipe_texture *pt, + struct winsys_handle *whandle) +{ + struct nouveau_miptree *mt = nouveau_miptree(pt); + + if (!mt || !mt->bo) + return false; + + whandle->stride = util_format_get_stride(mt->base.format, mt->base.width0); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + return nouveau_bo_handle_get(mt->bo, &whandle->handle) == 0; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = mt->bo->handle; + return TRUE; + } else { + return FALSE; + } +} + int nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) { @@ -258,6 +328,9 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) pscreen->fence_signalled = nouveau_screen_fence_signalled; pscreen->fence_finish = nouveau_screen_fence_finish; + pscreen->texture_from_handle = nouveau_screen_texture_from_handle; + pscreen->texture_get_handle = nouveau_screen_texture_get_handle; + return 0; } diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index a7927d88dfc..f4a7a2bc234 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -6,6 +6,18 @@ struct nouveau_screen { struct nouveau_device *device; struct nouveau_channel *channel; + /** + * Create a new texture object, using the given template info, but on top of + * existing memory. + * + * It is assumed that the buffer data is layed out according to the expected + * by the hardware. NULL will be returned if any inconsistency is found. + */ + struct pipe_texture * (*texture_blanket)(struct pipe_screen *, + const struct pipe_texture *templat, + const unsigned *stride, + struct pipe_buffer *buffer); + int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen, struct pipe_buffer *pb, unsigned usage); }; diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h index a10114beab9..7f16e31c3f0 100644 --- a/src/gallium/drivers/nouveau/nouveau_util.h +++ b/src/gallium/drivers/nouveau/nouveau_util.h @@ -88,4 +88,104 @@ static INLINE unsigned log2i(unsigned i) return r; } +struct u_split_prim { + void *priv; + void (*emit)(void *priv, unsigned start, unsigned count); + void (*edge)(void *priv, boolean enabled); + + unsigned mode; + unsigned start; + unsigned p_start; + unsigned p_end; + + int repeat_first:1; + int close_first:1; + int edgeflag_off:1; +}; + +static inline void +u_split_prim_init(struct u_split_prim *s, + unsigned mode, unsigned start, unsigned count) +{ + if (mode == PIPE_PRIM_LINE_LOOP) { + s->mode = PIPE_PRIM_LINE_STRIP; + s->close_first = 1; + } else { + s->mode = mode; + s->close_first = 0; + } + s->start = start; + s->p_start = start; + s->p_end = start + count; + s->edgeflag_off = 0; + s->repeat_first = 0; +} + +static INLINE boolean +u_split_prim_next(struct u_split_prim *s, unsigned max_verts) +{ + int repeat = 0; + + if (s->repeat_first) { + s->emit(s->priv, s->start, 1); + max_verts--; + if (s->edgeflag_off) { + s->edge(s->priv, TRUE); + s->edgeflag_off = FALSE; + } + } + + if (s->p_start + s->close_first + max_verts >= s->p_end) { + s->emit(s->priv, s->p_start, s->p_end - s->p_start); + if (s->close_first) + s->emit(s->priv, s->start, 1); + return TRUE; + } + + switch (s->mode) { + case PIPE_PRIM_LINES: + max_verts &= ~1; + break; + case PIPE_PRIM_LINE_STRIP: + repeat = 1; + break; + case PIPE_PRIM_POLYGON: + max_verts--; + s->emit(s->priv, s->p_start, max_verts); + s->edge(s->priv, FALSE); + s->emit(s->priv, s->p_start + max_verts, 1); + s->p_start += max_verts; + s->repeat_first = TRUE; + s->edgeflag_off = TRUE; + return FALSE; + case PIPE_PRIM_TRIANGLES: + max_verts = max_verts - (max_verts % 3); + break; + case PIPE_PRIM_TRIANGLE_STRIP: + /* to ensure winding stays correct, always split + * on an even number of generated triangles + */ + max_verts = max_verts & ~1; + repeat = 2; + break; + case PIPE_PRIM_TRIANGLE_FAN: + s->repeat_first = TRUE; + repeat = 1; + break; + case PIPE_PRIM_QUADS: + max_verts &= ~3; + break; + case PIPE_PRIM_QUAD_STRIP: + max_verts &= ~1; + repeat = 2; + break; + default: + break; + } + + s->emit (s->priv, s->p_start, max_verts); + s->p_start += (max_verts - repeat); + return FALSE; +} + #endif diff --git a/src/gallium/drivers/nouveau/nv04_surface_2d.c b/src/gallium/drivers/nouveau/nv04_surface_2d.c index b074547c4da..93114465d5e 100644 --- a/src/gallium/drivers/nouveau/nv04_surface_2d.c +++ b/src/gallium/drivers/nouveau/nv04_surface_2d.c @@ -518,7 +518,6 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d ns->base.usage = PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER | PIPE_BUFFER_USAGE_GPU_READ; } - struct nv40_screen* screen = (struct nv40_screen*)pscreen; ns->base.usage = PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE; struct pipe_texture templ; diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c index 279b74445ca..825c167b01b 100644 --- a/src/gallium/drivers/nv30/nv30_context.c +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -74,6 +74,7 @@ nv30_create(struct pipe_screen *pscreen, void *priv) nv30_init_query_functions(nv30); nv30_init_surface_functions(nv30); nv30_init_state_functions(nv30); + nv30_init_transfer_functions(nv30); /* Create, configure, and install fallback swtnl path */ nv30->draw = draw_create(); diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index ea259aadf35..4a164f3b1fd 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -107,6 +107,11 @@ struct nv30_state { struct nouveau_stateobj *hw[NV30_STATE_MAX]; }; +struct nv30_vtxelt_state { + struct pipe_vertex_element pipe[16]; + unsigned num_elements; +}; + struct nv30_context { struct pipe_context pipe; @@ -142,8 +147,7 @@ struct nv30_context { unsigned dirty_samplers; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - unsigned vtxelt_nr; + struct nv30_vtxelt_state *vtxelt; }; static INLINE struct nv30_context * @@ -163,6 +167,7 @@ struct nv30_state_entry { extern void nv30_init_state_functions(struct nv30_context *nv30); extern void nv30_init_surface_functions(struct nv30_context *nv30); extern void nv30_init_query_functions(struct nv30_context *nv30); +extern void nv30_init_transfer_functions(struct nv30_context *nv30); extern void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen); diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c index 697b1b92ff6..bfa27b632f7 100644 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nv30/nv30_miptree.c @@ -18,7 +18,7 @@ nv30_miptree_layout(struct nv30_miptree *nv30mt) PIPE_TEXTURE_USAGE_DEPTH_STENCIL | PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); + PIPE_TEXTURE_USAGE_SCANOUT); if (pt->target == PIPE_TEXTURE_CUBE) { nr_faces = 6; @@ -78,7 +78,7 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) pt->height0 & (pt->height0 - 1)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | + if (pt->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; @@ -232,8 +232,9 @@ void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen) { pscreen->texture_create = nv30_miptree_create; - pscreen->texture_blanket = nv30_miptree_blanket; pscreen->texture_destroy = nv30_miptree_destroy; pscreen->get_tex_surface = nv30_miptree_surface_new; pscreen->tex_surface_destroy = nv30_miptree_surface_del; + + nouveau_screen(pscreen)->texture_blanket = nv30_miptree_blanket; } diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 85433d20953..db24335b7c1 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -214,7 +214,6 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->context_create = nv30_create; nv30_screen_init_miptree_functions(pscreen); - nv30_screen_init_transfer_functions(pscreen); /* 3D object */ switch (dev->chipset & 0xf0) { diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index 8591cd31cab..b7856cdf005 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -35,7 +35,4 @@ nv30_screen(struct pipe_screen *screen) return (struct nv30_screen *)screen; } -void -nv30_screen_init_transfer_functions(struct pipe_screen *pscreen); - #endif diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c index d911c807074..24b15a63ac4 100644 --- a/src/gallium/drivers/nv30/nv30_state.c +++ b/src/gallium/drivers/nv30/nv30_state.c @@ -669,15 +669,34 @@ nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count, /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ } +static void * +nv30_vtxelts_state_create(struct pipe_context *pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct nv30_vtxelt_state *cso = CALLOC_STRUCT(nv30_vtxelt_state); + + assert(num_elements < 16); /* not doing fallbacks yet */ + cso->num_elements = num_elements; + memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); + +/* nv30_vtxelt_construct(cso);*/ + + return (void *)cso; +} + static void -nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *ve) +nv30_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) { - struct nv30_context *nv30 = nv30_context(pipe); + FREE(hwcso); +} - memcpy(nv30->vtxelt, ve, sizeof(*ve) * count); - nv30->vtxelt_nr = count; +static void +nv30_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nv30_context *nv30 = nv30_context(pipe); + nv30->vtxelt = hwcso; nv30->dirty |= NV30_NEW_ARRAYS; /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ } @@ -722,7 +741,10 @@ nv30_init_state_functions(struct nv30_context *nv30) nv30->pipe.set_scissor_state = nv30_set_scissor_state; nv30->pipe.set_viewport_state = nv30_set_viewport_state; + nv30->pipe.create_vertex_elements_state = nv30_vtxelts_state_create; + nv30->pipe.delete_vertex_elements_state = nv30_vtxelts_state_delete; + nv30->pipe.bind_vertex_elements_state = nv30_vtxelts_state_bind; + nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers; - nv30->pipe.set_vertex_elements = nv30_set_vertex_elements; } diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h index e42e872de75..66c26360cb2 100644 --- a/src/gallium/drivers/nv30/nv30_state.h +++ b/src/gallium/drivers/nv30/nv30_state.h @@ -70,6 +70,8 @@ struct nv30_fragment_program { struct nouveau_stateobj *so; }; +#define NV30_MAX_TEXTURE_LEVELS 16 + struct nv30_miptree { struct pipe_texture base; struct nouveau_bo *bo; @@ -80,7 +82,7 @@ struct nv30_miptree { struct { uint pitch; uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; + } level[NV30_MAX_TEXTURE_LEVELS]; }; #endif diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c index 3aeda51ea19..cfc109bb740 100644 --- a/src/gallium/drivers/nv30/nv30_transfer.c +++ b/src/gallium/drivers/nv30/nv30_transfer.c @@ -33,11 +33,12 @@ nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned h } static struct pipe_transfer * -nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +nv30_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, unsigned w, unsigned h) { + struct pipe_screen *pscreen = pcontext->screen; struct nv30_miptree *mt = (struct nv30_miptree *)pt; struct nv30_transfer *tx; struct pipe_texture tx_tex_template, *tx_tex; @@ -117,12 +118,13 @@ nv30_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } static void -nv30_transfer_del(struct pipe_transfer *ptx) +nv30_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx) { struct nv30_transfer *tx = (struct nv30_transfer *)ptx; if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; + struct pipe_screen *pscreen = pcontext->screen; struct nv30_screen *nvscreen = nv30_screen(pscreen); struct pipe_surface *dst; @@ -145,8 +147,9 @@ nv30_transfer_del(struct pipe_transfer *ptx) } static void * -nv30_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv30_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) { + struct pipe_screen *pscreen = pcontext->screen; struct nv30_transfer *tx = (struct nv30_transfer *)ptx; struct nv04_surface *ns = (struct nv04_surface *)tx->surface; struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; @@ -160,8 +163,9 @@ nv30_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } static void -nv30_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv30_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) { + struct pipe_screen *pscreen = pcontext->screen; struct nv30_transfer *tx = (struct nv30_transfer *)ptx; struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; @@ -169,10 +173,10 @@ nv30_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } void -nv30_screen_init_transfer_functions(struct pipe_screen *pscreen) +nv30_init_transfer_functions(struct nv30_context *nv30) { - pscreen->get_tex_transfer = nv30_transfer_new; - pscreen->tex_transfer_destroy = nv30_transfer_del; - pscreen->transfer_map = nv30_transfer_map; - pscreen->transfer_unmap = nv30_transfer_unmap; + nv30->pipe.get_tex_transfer = nv30_transfer_new; + nv30->pipe.tex_transfer_destroy = nv30_transfer_del; + nv30->pipe.transfer_map = nv30_transfer_map; + nv30->pipe.transfer_unmap = nv30_transfer_unmap; } diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c index e48823a9138..f3856bb5a5e 100644 --- a/src/gallium/drivers/nv30/nv30_vbo.c +++ b/src/gallium/drivers/nv30/nv30_vbo.c @@ -492,16 +492,16 @@ nv30_vbo_validate(struct nv30_context *nv30) int hw; vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr); + so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt->num_elements); vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr); + so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt->num_elements); - for (hw = 0; hw < nv30->vtxelt_nr; hw++) { + for (hw = 0; hw < nv30->vtxelt->num_elements; hw++) { struct pipe_vertex_element *ve; struct pipe_vertex_buffer *vb; unsigned type, ncomp; - ve = &nv30->vtxelt[hw]; + ve = &nv30->vtxelt->pipe[hw]; vb = &nv30->vtxbuf[ve->vertex_buffer_index]; if (!vb->stride) { diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index 65dc73e88b3..e828f17643b 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -74,6 +74,7 @@ nv40_create(struct pipe_screen *pscreen, void *priv) nv40_init_query_functions(nv40); nv40_init_surface_functions(nv40); nv40_init_state_functions(nv40); + nv40_init_transfer_functions(nv40); /* Create, configure, and install fallback swtnl path */ nv40->draw = draw_create(); diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index 97fb6a2ef94..cb5d9e2d9d4 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -107,6 +107,12 @@ struct nv40_state { struct nouveau_stateobj *hw[NV40_STATE_MAX]; }; + +struct nv40_vtxelt_state { + struct pipe_vertex_element pipe[16]; + unsigned num_elements; +}; + struct nv40_context { struct pipe_context pipe; @@ -157,8 +163,7 @@ struct nv40_context { unsigned dirty_samplers; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - unsigned vtxelt_nr; + struct nv40_vtxelt_state *vtxelt; }; static INLINE struct nv40_context * @@ -178,6 +183,7 @@ struct nv40_state_entry { extern void nv40_init_state_functions(struct nv40_context *nv40); extern void nv40_init_surface_functions(struct nv40_context *nv40); extern void nv40_init_query_functions(struct nv40_context *nv40); +extern void nv40_init_transfer_functions(struct nv40_context *nv40); extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen); diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c index 85d7e1f1972..62e97bcea48 100644 --- a/src/gallium/drivers/nv40/nv40_miptree.c +++ b/src/gallium/drivers/nv40/nv40_miptree.c @@ -20,7 +20,7 @@ nv40_miptree_layout(struct nv40_miptree *mt) PIPE_TEXTURE_USAGE_DEPTH_STENCIL | PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); + PIPE_TEXTURE_USAGE_SCANOUT); if (pt->target == PIPE_TEXTURE_CUBE) { nr_faces = 6; @@ -80,7 +80,7 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) pt->height0 & (pt->height0 - 1)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | + if (pt->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; @@ -227,9 +227,10 @@ void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen) { pscreen->texture_create = nv40_miptree_create; - pscreen->texture_blanket = nv40_miptree_blanket; pscreen->texture_destroy = nv40_miptree_destroy; pscreen->get_tex_surface = nv40_miptree_surface_new; pscreen->tex_surface_destroy = nv40_miptree_surface_del; + + nouveau_screen(pscreen)->texture_blanket = nv40_miptree_blanket; } diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index b216c5e38c9..dbcc33d8d9e 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -201,7 +201,6 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->context_create = nv40_create; nv40_screen_init_miptree_functions(pscreen); - nv40_screen_init_transfer_functions(pscreen); /* 3D object */ switch (dev->chipset & 0xf0) { diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 9437aa050d4..2765ab764ae 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -34,7 +34,4 @@ nv40_screen(struct pipe_screen *screen) return (struct nv40_screen *)screen; } -void -nv40_screen_init_transfer_functions(struct pipe_screen *pscreen); - #endif diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c index 4f28675e64c..ee471e6ce4c 100644 --- a/src/gallium/drivers/nv40/nv40_state.c +++ b/src/gallium/drivers/nv40/nv40_state.c @@ -684,15 +684,34 @@ nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count, nv40->draw_dirty |= NV40_NEW_ARRAYS; } +static void * +nv40_vtxelts_state_create(struct pipe_context *pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct nv40_vtxelt_state *cso = CALLOC_STRUCT(nv40_vtxelt_state); + + assert(num_elements < 16); /* not doing fallbacks yet */ + cso->num_elements = num_elements; + memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); + +/* nv40_vtxelt_construct(cso);*/ + + return (void *)cso; +} + static void -nv40_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *ve) +nv40_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) { - struct nv40_context *nv40 = nv40_context(pipe); + FREE(hwcso); +} - memcpy(nv40->vtxelt, ve, sizeof(*ve) * count); - nv40->vtxelt_nr = count; +static void +nv40_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nv40_context *nv40 = nv40_context(pipe); + nv40->vtxelt = hwcso; nv40->dirty |= NV40_NEW_ARRAYS; nv40->draw_dirty |= NV40_NEW_ARRAYS; } @@ -737,7 +756,10 @@ nv40_init_state_functions(struct nv40_context *nv40) nv40->pipe.set_scissor_state = nv40_set_scissor_state; nv40->pipe.set_viewport_state = nv40_set_viewport_state; + nv40->pipe.create_vertex_elements_state = nv40_vtxelts_state_create; + nv40->pipe.delete_vertex_elements_state = nv40_vtxelts_state_delete; + nv40->pipe.bind_vertex_elements_state = nv40_vtxelts_state_bind; + nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers; - nv40->pipe.set_vertex_elements = nv40_set_vertex_elements; } diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h index 192074e7471..e2e69420eae 100644 --- a/src/gallium/drivers/nv40/nv40_state.h +++ b/src/gallium/drivers/nv40/nv40_state.h @@ -73,6 +73,8 @@ struct nv40_fragment_program { struct nouveau_stateobj *so; }; +#define NV40_MAX_TEXTURE_LEVELS 16 + struct nv40_miptree { struct pipe_texture base; struct nouveau_bo *bo; @@ -83,7 +85,7 @@ struct nv40_miptree { struct { uint pitch; uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; + } level[NV40_MAX_TEXTURE_LEVELS]; }; #endif diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c index 8990f303ce4..297d71f4fac 100644 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ b/src/gallium/drivers/nv40/nv40_state_emit.c @@ -174,7 +174,7 @@ nv40_state_validate_swtnl(struct nv40_context *nv40) if (nv40->draw_dirty & NV40_NEW_ARRAYS) { draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf); - draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt); + draw_set_vertex_elements(draw, nv40->vtxelt->num_elements, nv40->vtxelt->pipe); } nv40_state_do_validate(nv40, swtnl_states); diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c index 0462a042c38..c552a681138 100644 --- a/src/gallium/drivers/nv40/nv40_transfer.c +++ b/src/gallium/drivers/nv40/nv40_transfer.c @@ -33,11 +33,12 @@ nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned h } static struct pipe_transfer * -nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +nv40_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, unsigned w, unsigned h) { + struct pipe_screen *pscreen = pcontext->screen; struct nv40_miptree *mt = (struct nv40_miptree *)pt; struct nv40_transfer *tx; struct pipe_texture tx_tex_template, *tx_tex; @@ -117,12 +118,12 @@ nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } static void -nv40_transfer_del(struct pipe_transfer *ptx) +nv40_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv40_transfer *tx = (struct nv40_transfer *)ptx; if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; + struct pipe_screen *pscreen = pcontext->screen; struct nv40_screen *nvscreen = nv40_screen(pscreen); struct pipe_surface *dst; @@ -145,8 +146,9 @@ nv40_transfer_del(struct pipe_transfer *ptx) } static void * -nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv40_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) { + struct pipe_screen *pscreen = pcontext->screen; struct nv40_transfer *tx = (struct nv40_transfer *)ptx; struct nv04_surface *ns = (struct nv04_surface *)tx->surface; struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; @@ -160,8 +162,9 @@ nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } static void -nv40_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv40_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) { + struct pipe_screen *pscreen = pcontext->screen; struct nv40_transfer *tx = (struct nv40_transfer *)ptx; struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; @@ -169,10 +172,10 @@ nv40_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } void -nv40_screen_init_transfer_functions(struct pipe_screen *pscreen) +nv40_init_transfer_functions(struct nv40_context *nv40) { - pscreen->get_tex_transfer = nv40_transfer_new; - pscreen->tex_transfer_destroy = nv40_transfer_del; - pscreen->transfer_map = nv40_transfer_map; - pscreen->transfer_unmap = nv40_transfer_unmap; + nv40->pipe.get_tex_transfer = nv40_transfer_new; + nv40->pipe.tex_transfer_destroy = nv40_transfer_del; + nv40->pipe.transfer_map = nv40_transfer_map; + nv40->pipe.transfer_unmap = nv40_transfer_unmap; } diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c index 7812460d2ed..fabdf4bf23b 100644 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ b/src/gallium/drivers/nv40/nv40_vbo.c @@ -493,16 +493,16 @@ nv40_vbo_validate(struct nv40_context *nv40) int hw; vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr); + so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt->num_elements); vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt_nr); + so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt->num_elements); - for (hw = 0; hw < nv40->vtxelt_nr; hw++) { + for (hw = 0; hw < nv40->vtxelt->num_elements; hw++) { struct pipe_vertex_element *ve; struct pipe_vertex_buffer *vb; unsigned type, ncomp; - ve = &nv40->vtxelt[hw]; + ve = &nv40->vtxelt->pipe[hw]; vb = &nv40->vtxbuf[ve->vertex_buffer_index]; if (!vb->stride) { diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index 612aea28a34..5d622e1c13c 100644 --- a/src/gallium/drivers/nv50/Makefile +++ b/src/gallium/drivers/nv50/Makefile @@ -16,6 +16,7 @@ C_SOURCES = \ nv50_surface.c \ nv50_tex.c \ nv50_transfer.c \ - nv50_vbo.c + nv50_vbo.c \ + nv50_push.c include ../../Makefile.template diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c index e0b2d2880b0..8afc95c9fc6 100644 --- a/src/gallium/drivers/nv50/nv50_clear.c +++ b/src/gallium/drivers/nv50/nv50_clear.c @@ -36,7 +36,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned mode = 0, i; - if (!nv50_state_validate(nv50)) + if (!nv50_state_validate(nv50, 64)) return; if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 7be12fcdef4..aa14e17872d 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -46,43 +46,13 @@ static void nv50_destroy(struct pipe_context *pipe) { struct nv50_context *nv50 = nv50_context(pipe); + int i; - if (nv50->state.fb) - so_ref(NULL, &nv50->state.fb); - if (nv50->state.blend) - so_ref(NULL, &nv50->state.blend); - if (nv50->state.blend_colour) - so_ref(NULL, &nv50->state.blend_colour); - if (nv50->state.zsa) - so_ref(NULL, &nv50->state.zsa); - if (nv50->state.rast) - so_ref(NULL, &nv50->state.rast); - if (nv50->state.stipple) - so_ref(NULL, &nv50->state.stipple); - if (nv50->state.scissor) - so_ref(NULL, &nv50->state.scissor); - if (nv50->state.viewport) - so_ref(NULL, &nv50->state.viewport); - if (nv50->state.tsc_upload) - so_ref(NULL, &nv50->state.tsc_upload); - if (nv50->state.tic_upload) - so_ref(NULL, &nv50->state.tic_upload); - if (nv50->state.vertprog) - so_ref(NULL, &nv50->state.vertprog); - if (nv50->state.fragprog) - so_ref(NULL, &nv50->state.fragprog); - if (nv50->state.geomprog) - so_ref(NULL, &nv50->state.geomprog); - if (nv50->state.fp_linkage) - so_ref(NULL, &nv50->state.fp_linkage); - if (nv50->state.gp_linkage) - so_ref(NULL, &nv50->state.gp_linkage); - if (nv50->state.vtxfmt) - so_ref(NULL, &nv50->state.vtxfmt); - if (nv50->state.vtxbuf) - so_ref(NULL, &nv50->state.vtxbuf); - if (nv50->state.vtxattr) - so_ref(NULL, &nv50->state.vtxattr); + for (i = 0; i < 64; i++) { + if (!nv50->state.hw[i]) + continue; + so_ref(NULL, &nv50->state.hw[i]); + } draw_destroy(nv50->draw); @@ -123,11 +93,11 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; screen->base.channel->user_private = nv50; - screen->base.channel->flush_notify = nv50_state_flush_notify; nv50_init_surface_functions(nv50); nv50_init_state_functions(nv50); nv50_init_query_functions(nv50); + nv50_init_transfer_functions(nv50); nv50->draw = draw_create(); assert(nv50->draw); diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index c540594b949..1743f6fb394 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -72,6 +72,12 @@ struct nv50_sampler_stateobj { unsigned tsc[8]; }; +struct nv50_vtxelt_stateobj { + struct pipe_vertex_element pipe[16]; + unsigned num_elements; + uint32_t hw[16]; +}; + static INLINE unsigned get_tile_height(uint32_t tile_mode) { @@ -90,10 +96,12 @@ struct nv50_miptree_level { unsigned tile_mode; }; +#define NV50_MAX_TEXTURE_LEVELS 16 + struct nv50_miptree { struct nouveau_miptree base; - struct nv50_miptree_level level[PIPE_MAX_TEXTURE_LEVELS]; + struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS]; int image_nr; int total_size; }; @@ -115,30 +123,12 @@ nv50_surface(struct pipe_surface *pt) } struct nv50_state { - unsigned dirty; + struct nouveau_stateobj *hw[64]; + uint64_t hw_dirty; - struct nouveau_stateobj *fb; - struct nouveau_stateobj *blend; - struct nouveau_stateobj *blend_colour; - struct nouveau_stateobj *zsa; - struct nouveau_stateobj *stencil_ref; - struct nouveau_stateobj *rast; - struct nouveau_stateobj *stipple; - struct nouveau_stateobj *scissor; - unsigned scissor_enabled; - struct nouveau_stateobj *viewport; - struct nouveau_stateobj *tsc_upload; - struct nouveau_stateobj *tic_upload; unsigned miptree_nr[PIPE_SHADER_TYPES]; - struct nouveau_stateobj *vertprog; - struct nouveau_stateobj *fragprog; - struct nouveau_stateobj *geomprog; - struct nouveau_stateobj *fp_linkage; - struct nouveau_stateobj *gp_linkage; - struct nouveau_stateobj *vtxfmt; struct nouveau_stateobj *vtxbuf; struct nouveau_stateobj *vtxattr; - struct nouveau_stateobj *instbuf; unsigned vtxelt_nr; }; @@ -167,14 +157,13 @@ struct nv50_context { struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - unsigned vtxelt_nr; + struct nv50_vtxelt_stateobj *vtxelt; struct nv50_sampler_stateobj *sampler[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; unsigned sampler_nr[PIPE_SHADER_TYPES]; struct nv50_miptree *miptree[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; unsigned miptree_nr[PIPE_SHADER_TYPES]; - uint16_t vbo_fifo; + unsigned vbo_fifo; }; static INLINE struct nv50_context * @@ -186,6 +175,7 @@ nv50_context(struct pipe_context *pipe) extern void nv50_init_surface_functions(struct nv50_context *nv50); extern void nv50_init_state_functions(struct nv50_context *nv50); extern void nv50_init_query_functions(struct nv50_context *nv50); +extern void nv50_init_transfer_functions(struct nv50_context *nv50); extern void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen); @@ -216,24 +206,36 @@ extern void nv50_draw_elements_instanced(struct pipe_context *pipe, unsigned count, unsigned startInstance, unsigned instanceCount); -extern void nv50_vbo_validate(struct nv50_context *nv50); +extern void nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso); +extern struct nouveau_stateobj *nv50_vbo_validate(struct nv50_context *nv50); + +/* nv50_push.c */ +extern void +nv50_push_elements_instanced(struct pipe_context *, struct pipe_buffer *, + unsigned idxsize, unsigned mode, unsigned start, + unsigned count, unsigned i_start, + unsigned i_count); /* nv50_clear.c */ extern void nv50_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil); /* nv50_program.c */ -extern void nv50_vertprog_validate(struct nv50_context *nv50); -extern void nv50_fragprog_validate(struct nv50_context *nv50); -extern void nv50_geomprog_validate(struct nv50_context *nv50); -extern void nv50_fp_linkage_validate(struct nv50_context *nv50); -extern void nv50_gp_linkage_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_vertprog_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_fragprog_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_geomprog_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_fp_linkage_validate(struct nv50_context *nv50); +extern struct nouveau_stateobj * +nv50_gp_linkage_validate(struct nv50_context *nv50); extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p); /* nv50_state_validate.c */ -extern boolean nv50_state_validate(struct nv50_context *nv50); -extern void nv50_state_flush_notify(struct nouveau_channel *chan); +extern boolean nv50_state_validate(struct nv50_context *nv50, unsigned dwords); extern void nv50_so_init_sifc(struct nv50_context *nv50, struct nouveau_stateobj *so, @@ -241,7 +243,8 @@ extern void nv50_so_init_sifc(struct nv50_context *nv50, unsigned offset, unsigned size); /* nv50_tex.c */ -extern void nv50_tex_validate(struct nv50_context *); +extern void nv50_tex_relocs(struct nv50_context *); +extern struct nouveau_stateobj *nv50_tex_validate(struct nv50_context *); /* nv50_transfer.c */ extern void @@ -255,4 +258,35 @@ nv50_upload_sifc(struct nv50_context *nv50, struct pipe_context * nv50_create(struct pipe_screen *pscreen, void *priv); +static INLINE unsigned +nv50_prim(unsigned mode) +{ + switch (mode) { + case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS; + case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES; + case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP; + case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP; + case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES; + case PIPE_PRIM_TRIANGLE_STRIP: + return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP; + case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN; + case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS; + case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP; + case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON; + case PIPE_PRIM_LINES_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY; + default: + break; + } + + NOUVEAU_ERR("invalid primitive type %d\n", mode); + return NV50TCL_VERTEX_BEGIN_POINTS; +} + #endif diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index 3f9d869d7a4..e091cae6024 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -104,7 +104,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) tile_flags = 0x7400; break; default: - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) && + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) && util_format_get_blocksizebits(pt->format) == 32) tile_flags = 0x7a00; else @@ -255,9 +255,10 @@ void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen) { pscreen->texture_create = nv50_miptree_create; - pscreen->texture_blanket = nv50_miptree_blanket; pscreen->texture_destroy = nv50_miptree_destroy; pscreen->get_tex_surface = nv50_miptree_surface_new; pscreen->tex_surface_destroy = nv50_miptree_surface_del; + + nouveau_screen(pscreen)->texture_blanket = nv50_miptree_blanket; } diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 2372cbbef69..c857816b31a 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -4270,7 +4270,7 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) FREE(up); } -void +struct nouveau_stateobj * nv50_vertprog_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4286,6 +4286,9 @@ nv50_vertprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); + if (!(nv50->dirty & NV50_NEW_VERTPROG)) + return NULL; + so = so_new(5, 7, 2); so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | @@ -4301,11 +4304,10 @@ nv50_vertprog_validate(struct nv50_context *nv50) so_data (so, p->cfg.high_temp); so_method(so, tesla, NV50TCL_VP_START_ID, 1); so_data (so, 0); /* program start offset */ - so_ref(so, &nv50->state.vertprog); - so_ref(NULL, &so); + return so; } -void +struct nouveau_stateobj * nv50_fragprog_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4321,6 +4323,9 @@ nv50_fragprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); + if (!(nv50->dirty & NV50_NEW_FRAGPROG)) + return NULL; + so = so_new(6, 7, 2); so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | @@ -4337,11 +4342,10 @@ nv50_fragprog_validate(struct nv50_context *nv50) so_data (so, p->cfg.regs[3]); so_method(so, tesla, NV50TCL_FP_START_ID, 1); so_data (so, 0); /* program start offset */ - so_ref(so, &nv50->state.fragprog); - so_ref(NULL, &so); + return so; } -void +struct nouveau_stateobj * nv50_geomprog_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4357,6 +4361,9 @@ nv50_geomprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); + if (!(nv50->dirty & NV50_NEW_GEOMPROG)) + return NULL; + so = so_new(6, 7, 2); so_method(so, tesla, NV50TCL_GP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | @@ -4373,8 +4380,7 @@ nv50_geomprog_validate(struct nv50_context *nv50) so_data (so, p->cfg.vert_count); so_method(so, tesla, NV50TCL_GP_START_ID, 1); so_data (so, 0); - so_ref(so, &nv50->state.geomprog); - so_ref(NULL, &so); + return so; } static uint32_t @@ -4454,7 +4460,7 @@ nv50_vec4_map(uint32_t *map32, int mid, uint8_t zval, uint32_t lin[4], return mid; } -void +struct nouveau_stateobj * nv50_fp_linkage_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4580,8 +4586,7 @@ nv50_fp_linkage_validate(struct nv50_context *nv50) so_method(so, tesla, NV50TCL_GP_ENABLE, 1); so_data (so, (vp->type == PIPE_SHADER_GEOMETRY) ? 1 : 0); - so_ref(so, &nv50->state.fp_linkage); - so_ref(NULL, &so); + return so; } static int @@ -4615,7 +4620,7 @@ construct_vp_gp_mapping(uint32_t *map32, int m, return m; } -void +struct nouveau_stateobj * nv50_gp_linkage_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -4625,10 +4630,8 @@ nv50_gp_linkage_validate(struct nv50_context *nv50) uint32_t map[16]; int m = 0; - if (!gp) { - so_ref(NULL, &nv50->state.gp_linkage); - return; - } + if (!gp) + return NULL; memset(map, 0, sizeof(map)); m = construct_vp_gp_mapping(map, m, vp, gp); @@ -4646,8 +4649,7 @@ nv50_gp_linkage_validate(struct nv50_context *nv50) so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), m); so_datap (so, map, m); - so_ref(so, &nv50->state.gp_linkage); - so_ref(NULL, &so); + return so; } void diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c new file mode 100644 index 00000000000..96a1f32d304 --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_push.c @@ -0,0 +1,326 @@ +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_inlines.h" +#include "util/u_format.h" + +#include "nouveau/nouveau_util.h" +#include "nv50_context.h" + +struct push_context { + struct nv50_context *nv50; + + unsigned vtx_size; + + void *idxbuf; + unsigned idxsize; + + float edgeflag; + int edgeflag_attr; + + struct { + void *map; + unsigned stride; + unsigned divisor; + unsigned step; + void (*push)(struct nouveau_channel *, void *); + } attr[16]; + unsigned attr_nr; +}; + +static void +emit_b32_1(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); +} + +static void +emit_b32_2(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); + OUT_RING(chan, v[1]); +} + +static void +emit_b32_3(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); + OUT_RING(chan, v[1]); + OUT_RING(chan, v[2]); +} + +static void +emit_b32_4(struct nouveau_channel *chan, void *data) +{ + uint32_t *v = data; + + OUT_RING(chan, v[0]); + OUT_RING(chan, v[1]); + OUT_RING(chan, v[2]); + OUT_RING(chan, v[3]); +} + +static void +emit_b16_1(struct nouveau_channel *chan, void *data) +{ + uint16_t *v = data; + + OUT_RING(chan, v[0]); +} + +static void +emit_b16_3(struct nouveau_channel *chan, void *data) +{ + uint16_t *v = data; + + OUT_RING(chan, (v[1] << 16) | v[0]); + OUT_RING(chan, v[2]); +} + +static void +emit_b08_1(struct nouveau_channel *chan, void *data) +{ + uint8_t *v = data; + + OUT_RING(chan, v[0]); +} + +static void +emit_b08_3(struct nouveau_channel *chan, void *data) +{ + uint8_t *v = data; + + OUT_RING(chan, (v[2] << 16) | (v[1] << 8) | v[0]); +} + +static INLINE void +emit_vertex(struct push_context *ctx, unsigned n) +{ + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + int i; + + if (ctx->edgeflag_attr < 16) { + float *edgeflag = ctx->attr[ctx->edgeflag_attr].map + + ctx->attr[ctx->edgeflag_attr].stride * n; + + if (*edgeflag != ctx->edgeflag) { + BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, *edgeflag ? 1 : 0); + ctx->edgeflag = *edgeflag; + } + } + + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, ctx->vtx_size); + for (i = 0; i < ctx->attr_nr; i++) + ctx->attr[i].push(chan, ctx->attr[i].map + ctx->attr[i].stride * n); +} + +static void +emit_edgeflag(void *priv, boolean enabled) +{ + struct push_context *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + + BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, enabled ? 1 : 0); +} + +static void +emit_elt08(void *priv, unsigned start, unsigned count) +{ + struct push_context *ctx = priv; + uint8_t *idxbuf = ctx->idxbuf; + + while (count--) + emit_vertex(ctx, idxbuf[start++]); +} + +static void +emit_elt16(void *priv, unsigned start, unsigned count) +{ + struct push_context *ctx = priv; + uint16_t *idxbuf = ctx->idxbuf; + + while (count--) + emit_vertex(ctx, idxbuf[start++]); +} + +static void +emit_elt32(void *priv, unsigned start, unsigned count) +{ + struct push_context *ctx = priv; + uint32_t *idxbuf = ctx->idxbuf; + + while (count--) + emit_vertex(ctx, idxbuf[start++]); +} + +static void +emit_verts(void *priv, unsigned start, unsigned count) +{ + while (count--) + emit_vertex(priv, start++); +} + +void +nv50_push_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *idxbuf, unsigned idxsize, + unsigned mode, unsigned start, unsigned count, + unsigned i_start, unsigned i_count) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct push_context ctx; + const unsigned p_overhead = 4 + /* begin/end */ + 4; /* potential edgeflag enable/disable */ + const unsigned v_overhead = 1 + /* VERTEX_DATA packet header */ + 2; /* potential edgeflag modification */ + struct u_split_prim s; + unsigned vtx_size; + boolean nzi = FALSE; + int i; + + ctx.nv50 = nv50; + ctx.attr_nr = 0; + ctx.idxbuf = NULL; + ctx.vtx_size = 0; + ctx.edgeflag = 0.5f; + ctx.edgeflag_attr = nv50->vertprog->cfg.edgeflag_in; + + /* map vertex buffers, determine vertex size */ + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; + struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; + struct nouveau_bo *bo = nouveau_bo(vb->buffer); + unsigned size, nr_components, n; + + if (!(nv50->vbo_fifo & (1 << i))) + continue; + n = ctx.attr_nr++; + + if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) { + assert(bo->map); + return; + } + ctx.attr[n].map = bo->map + vb->buffer_offset + ve->src_offset; + nouveau_bo_unmap(bo); + + ctx.attr[n].stride = vb->stride; + ctx.attr[n].divisor = ve->instance_divisor; + if (ctx.attr[n].divisor) { + ctx.attr[n].step = i_start % ve->instance_divisor; + ctx.attr[n].map += i_start * vb->stride; + } + + size = util_format_get_component_bits(ve->src_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + nr_components = util_format_get_nr_components(ve->src_format); + switch (size) { + case 8: + switch (nr_components) { + case 1: ctx.attr[n].push = emit_b08_1; break; + case 2: ctx.attr[n].push = emit_b16_1; break; + case 3: ctx.attr[n].push = emit_b08_3; break; + case 4: ctx.attr[n].push = emit_b32_1; break; + } + ctx.vtx_size++; + break; + case 16: + switch (nr_components) { + case 1: ctx.attr[n].push = emit_b16_1; break; + case 2: ctx.attr[n].push = emit_b32_1; break; + case 3: ctx.attr[n].push = emit_b16_3; break; + case 4: ctx.attr[n].push = emit_b32_2; break; + } + ctx.vtx_size += (nr_components + 1) >> 1; + break; + case 32: + switch (nr_components) { + case 1: ctx.attr[n].push = emit_b32_1; break; + case 2: ctx.attr[n].push = emit_b32_2; break; + case 3: ctx.attr[n].push = emit_b32_3; break; + case 4: ctx.attr[n].push = emit_b32_4; break; + } + ctx.vtx_size += nr_components; + break; + default: + assert(0); + return; + } + } + vtx_size = ctx.vtx_size + v_overhead; + + /* map index buffer, if present */ + if (idxbuf) { + struct nouveau_bo *bo = nouveau_bo(idxbuf); + + if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) { + assert(bo->map); + return; + } + ctx.idxbuf = bo->map; + ctx.idxsize = idxsize; + nouveau_bo_unmap(bo); + } + + s.priv = &ctx; + s.edge = emit_edgeflag; + if (idxbuf) { + if (idxsize == 1) + s.emit = emit_elt08; + else + if (idxsize == 2) + s.emit = emit_elt16; + else + s.emit = emit_elt32; + } else + s.emit = emit_verts; + + /* per-instance loop */ + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, i_start); + while (i_count--) { + unsigned max_verts; + boolean done; + + for (i = 0; i < ctx.attr_nr; i++) { + if (!ctx.attr[i].divisor || + ctx.attr[i].divisor != ++ctx.attr[i].step) + continue; + ctx.attr[i].step = 0; + ctx.attr[i].map += ctx.attr[i].stride; + } + + u_split_prim_init(&s, mode, start, count); + do { + if (AVAIL_RING(chan) < p_overhead + (6 * vtx_size)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, p_overhead + (6 * vtx_size))) { + assert(0); + return; + } + } + + max_verts = AVAIL_RING(chan); + max_verts -= p_overhead; + max_verts /= vtx_size; + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1 << 28) : 0)); + done = u_split_prim_next(&s, max_verts); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } while (!done); + + nzi = TRUE; + } +} diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index eed6031eafa..7e2e8aa336e 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -95,6 +95,8 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, static int nv50_screen_get_param(struct pipe_screen *pscreen, int param) { + struct nv50_screen *screen = nv50_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: return 32; @@ -132,9 +134,9 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; case NOUVEAU_CAP_HW_VTXBUF: - return 1; + return screen->force_push ? 0 : 1; case NOUVEAU_CAP_HW_IDXBUF: - return 1; + return screen->force_push ? 0 : 1; case PIPE_CAP_INDEP_BLEND_ENABLE: return 1; case PIPE_CAP_INDEP_BLEND_FUNC: @@ -202,28 +204,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen) FREE(screen); } -static int -nv50_pre_pipebuffer_map(struct pipe_screen *pscreen, struct pipe_buffer *pb, - unsigned usage) -{ - struct nv50_screen *screen = nv50_screen(pscreen); - struct nv50_context *ctx = screen->cur_ctx; - - if (!(pb->usage & PIPE_BUFFER_USAGE_VERTEX)) - return 0; - - /* Our vtxbuf got mapped, it can no longer be considered part of current - * state, remove it to avoid emitting reloc markers. - */ - if (ctx && ctx->state.vtxbuf && so_bo_is_reloc(ctx->state.vtxbuf, - nouveau_bo(pb))) { - so_ref(NULL, &ctx->state.vtxbuf); - ctx->dirty |= NV50_NEW_ARRAYS; - } - - return 0; -} - struct pipe_screen * nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { @@ -252,7 +232,6 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_paramf = nv50_screen_get_paramf; pscreen->is_format_supported = nv50_screen_is_format_supported; pscreen->context_create = nv50_create; - screen->base.pre_pipebuffer_map_callback = nv50_pre_pipebuffer_map; nv50_screen_init_miptree_functions(pscreen); nv50_transfer_init_screen_functions(pscreen); @@ -508,10 +487,6 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, NV50TCL_LINKED_TSC, 1); so_data (so, 1); - /* activate first scissor rectangle */ - so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE(0), 1); - so_data (so, 1); - so_method(so, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1); so_data (so, 1); /* default edgeflag to TRUE */ @@ -520,6 +495,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_ref (NULL, &so); nouveau_pushbuf_flush(chan, 0); + screen->force_push = debug_get_bool_option("NV50_ALWAYS_PUSH", FALSE); return pscreen; } diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 2687b721277..d1bc80cb9ed 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -28,6 +28,8 @@ struct nv50_screen { struct nouveau_bo *tsc; struct nouveau_stateobj *static_init; + + boolean force_push; }; static INLINE struct nv50_screen * diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 7d304907b65..b0e5552eff4 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -302,7 +302,7 @@ static void * nv50_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { - struct nouveau_stateobj *so = so_new(15, 21, 0); + struct nouveau_stateobj *so = so_new(16, 22, 0); struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; struct nv50_rasterizer_stateobj *rso = CALLOC_STRUCT(nv50_rasterizer_stateobj); @@ -314,6 +314,9 @@ nv50_rasterizer_state_create(struct pipe_context *pipe, * - point_sprite / sprite_coord_mode */ + so_method(so, tesla, NV50TCL_SCISSOR_ENABLE(0), 1); + so_data (so, cso->scissor); + so_method(so, tesla, NV50TCL_SHADE_MODEL, 1); so_data (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT : NV50TCL_SHADE_MODEL_SMOOTH); @@ -720,15 +723,34 @@ nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count, nv50->dirty |= NV50_NEW_ARRAYS; } +static void * +nv50_vtxelts_state_create(struct pipe_context *pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct nv50_vtxelt_stateobj *cso = CALLOC_STRUCT(nv50_vtxelt_stateobj); + + assert(num_elements < 16); /* not doing fallbacks yet */ + cso->num_elements = num_elements; + memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); + + nv50_vtxelt_construct(cso); + + return (void *)cso; +} + static void -nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *ve) +nv50_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) { - struct nv50_context *nv50 = nv50_context(pipe); + FREE(hwcso); +} - memcpy(nv50->vtxelt, ve, sizeof(*ve) * count); - nv50->vtxelt_nr = count; +static void +nv50_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nv50_context *nv50 = nv50_context(pipe); + nv50->vtxelt = hwcso; nv50->dirty |= NV50_NEW_ARRAYS; } @@ -778,7 +800,10 @@ nv50_init_state_functions(struct nv50_context *nv50) nv50->pipe.set_scissor_state = nv50_set_scissor_state; nv50->pipe.set_viewport_state = nv50_set_viewport_state; + nv50->pipe.create_vertex_elements_state = nv50_vtxelts_state_create; + nv50->pipe.delete_vertex_elements_state = nv50_vtxelts_state_delete; + nv50->pipe.bind_vertex_elements_state = nv50_vtxelts_state_bind; + nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers; - nv50->pipe.set_vertex_elements = nv50_set_vertex_elements; } diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index c974cc92dcc..2c8e7ca7982 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -25,8 +25,8 @@ #include "nv50_context.h" #include "nouveau/nouveau_stateobj.h" -static void -nv50_state_validate_fb(struct nv50_context *nv50) +static struct nouveau_stateobj * +validate_fb(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; struct nouveau_stateobj *so = so_new(32, 79, 18); @@ -167,12 +167,7 @@ nv50_state_validate_fb(struct nv50_context *nv50) so_data (so, w << 16); so_data (so, h << 16); - /* we set scissors to framebuffer size when they're 'turned off' */ - nv50->dirty |= NV50_NEW_SCISSOR; - so_ref(NULL, &nv50->state.scissor); - - so_ref(so, &nv50->state.fb); - so_ref(NULL, &so); + return so; } static void @@ -199,263 +194,256 @@ nv50_validate_samplers(struct nv50_context *nv50, struct nouveau_stateobj *so, } } -static void -nv50_state_emit(struct nv50_context *nv50) +static struct nouveau_stateobj * +validate_blend(struct nv50_context *nv50) { - struct nv50_screen *screen = nv50->screen; - struct nouveau_channel *chan = screen->base.channel; + struct nouveau_stateobj *so = NULL; + so_ref(nv50->blend->so, &so); + return so; +} - /* XXX: this is racy for multiple contexts active on separate - * threads. - */ - if (screen->cur_ctx != nv50) { - if (nv50->state.fb) - nv50->state.dirty |= NV50_NEW_FRAMEBUFFER; - if (nv50->state.blend) - nv50->state.dirty |= NV50_NEW_BLEND; - if (nv50->state.zsa) - nv50->state.dirty |= NV50_NEW_ZSA; - if (nv50->state.vertprog) - nv50->state.dirty |= NV50_NEW_VERTPROG; - if (nv50->state.fragprog) - nv50->state.dirty |= NV50_NEW_FRAGPROG; - if (nv50->state.geomprog) - nv50->state.dirty |= NV50_NEW_GEOMPROG; - if (nv50->state.rast) - nv50->state.dirty |= NV50_NEW_RASTERIZER; - if (nv50->state.blend_colour) - nv50->state.dirty |= NV50_NEW_BLEND_COLOUR; - if (nv50->state.stencil_ref) - nv50->state.dirty |= NV50_NEW_STENCIL_REF; - if (nv50->state.stipple) - nv50->state.dirty |= NV50_NEW_STIPPLE; - if (nv50->state.scissor) - nv50->state.dirty |= NV50_NEW_SCISSOR; - if (nv50->state.viewport) - nv50->state.dirty |= NV50_NEW_VIEWPORT; - if (nv50->state.tsc_upload) - nv50->state.dirty |= NV50_NEW_SAMPLER; - if (nv50->state.tic_upload) - nv50->state.dirty |= NV50_NEW_TEXTURE; - if (nv50->state.vtxfmt && nv50->state.vtxbuf) - nv50->state.dirty |= NV50_NEW_ARRAYS; - screen->cur_ctx = nv50; - } +static struct nouveau_stateobj * +validate_zsa(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->zsa->so, &so); + return so; +} - if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER) - so_emit(chan, nv50->state.fb); - if (nv50->state.dirty & NV50_NEW_BLEND) - so_emit(chan, nv50->state.blend); - if (nv50->state.dirty & NV50_NEW_ZSA) - so_emit(chan, nv50->state.zsa); - if (nv50->state.dirty & NV50_NEW_VERTPROG) - so_emit(chan, nv50->state.vertprog); - if (nv50->state.dirty & NV50_NEW_FRAGPROG) - so_emit(chan, nv50->state.fragprog); - if (nv50->state.dirty & NV50_NEW_GEOMPROG && nv50->state.geomprog) - so_emit(chan, nv50->state.geomprog); - if (nv50->state.dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | - NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER)) - so_emit(chan, nv50->state.fp_linkage); - if ((nv50->state.dirty & (NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG)) - && nv50->state.gp_linkage) - so_emit(chan, nv50->state.gp_linkage); - if (nv50->state.dirty & NV50_NEW_RASTERIZER) - so_emit(chan, nv50->state.rast); - if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR) - so_emit(chan, nv50->state.blend_colour); - if (nv50->state.dirty & NV50_NEW_STENCIL_REF) - so_emit(chan, nv50->state.stencil_ref); - if (nv50->state.dirty & NV50_NEW_STIPPLE) - so_emit(chan, nv50->state.stipple); - if (nv50->state.dirty & NV50_NEW_SCISSOR) - so_emit(chan, nv50->state.scissor); - if (nv50->state.dirty & NV50_NEW_VIEWPORT) - so_emit(chan, nv50->state.viewport); - if (nv50->state.dirty & NV50_NEW_SAMPLER) - so_emit(chan, nv50->state.tsc_upload); - if (nv50->state.dirty & NV50_NEW_TEXTURE) - so_emit(chan, nv50->state.tic_upload); - if (nv50->state.dirty & NV50_NEW_ARRAYS) { - so_emit(chan, nv50->state.vtxfmt); - so_emit(chan, nv50->state.vtxbuf); - if (nv50->state.vtxattr) - so_emit(chan, nv50->state.vtxattr); - } - nv50->state.dirty = 0; +static struct nouveau_stateobj * +validate_rast(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->rasterizer->so, &so); + return so; } -void -nv50_state_flush_notify(struct nouveau_channel *chan) +static struct nouveau_stateobj * +validate_blend_colour(struct nv50_context *nv50) { - struct nv50_context *nv50 = chan->user_private; + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so_new(1, 4, 0); + + so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4); + so_data (so, fui(nv50->blend_colour.color[0])); + so_data (so, fui(nv50->blend_colour.color[1])); + so_data (so, fui(nv50->blend_colour.color[2])); + so_data (so, fui(nv50->blend_colour.color[3])); + return so; +} - if (nv50->state.tic_upload && !(nv50->dirty & NV50_NEW_TEXTURE)) - so_emit(chan, nv50->state.tic_upload); +static struct nouveau_stateobj * +validate_stencil_ref(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so = so_new(2, 2, 0); - so_emit_reloc_markers(chan, nv50->state.fb); - so_emit_reloc_markers(chan, nv50->state.vertprog); - so_emit_reloc_markers(chan, nv50->state.fragprog); - so_emit_reloc_markers(chan, nv50->state.vtxbuf); - so_emit_reloc_markers(chan, nv50->screen->static_init); + so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 1); + so_data (so, nv50->stencil_ref.ref_value[0]); + so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 1); + so_data (so, nv50->stencil_ref.ref_value[1]); + return so; +} - if (nv50->state.instbuf) - so_emit_reloc_markers(chan, nv50->state.instbuf); +static struct nouveau_stateobj * +validate_stipple(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so_new(1, 32, 0); + int i; + + so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); + for (i = 0; i < 32; i++) + so_data(so, util_bswap32(nv50->stipple.stipple[i])); + return so; } -boolean -nv50_state_validate(struct nv50_context *nv50) +static struct nouveau_stateobj * +validate_scissor(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; + struct pipe_scissor_state *s = &nv50->scissor; struct nouveau_stateobj *so; - unsigned i; - if (nv50->dirty & NV50_NEW_FRAMEBUFFER) - nv50_state_validate_fb(nv50); + so = so_new(1, 2, 0); + so_method(so, tesla, NV50TCL_SCISSOR_HORIZ(0), 2); + so_data (so, (s->maxx << 16) | s->minx); + so_data (so, (s->maxy << 16) | s->miny); + return so; +} + +static struct nouveau_stateobj * +validate_viewport(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so = so_new(5, 9, 0); + + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3); + so_data (so, fui(nv50->viewport.translate[0])); + so_data (so, fui(nv50->viewport.translate[1])); + so_data (so, fui(nv50->viewport.translate[2])); + so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3); + so_data (so, fui(nv50->viewport.scale[0])); + so_data (so, fui(nv50->viewport.scale[1])); + so_data (so, fui(nv50->viewport.scale[2])); + + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); + so_data (so, 1); + /* 0x0000 = remove whole primitive only (xyz) + * 0x1018 = remove whole primitive only (xy), clamp z + * 0x1080 = clip primitive (xyz) + * 0x1098 = clip primitive (xy), clamp z + */ + so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); + so_data (so, 0x1080); + /* no idea what 0f90 does */ + so_method(so, tesla, 0x0f90, 1); + so_data (so, 0); + + return so; +} - if (nv50->dirty & NV50_NEW_BLEND) - so_ref(nv50->blend->so, &nv50->state.blend); +static struct nouveau_stateobj * +validate_sampler(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so; + unsigned nr = 0, i; - if (nv50->dirty & NV50_NEW_ZSA) - so_ref(nv50->zsa->so, &nv50->state.zsa); + for (i = 0; i < PIPE_SHADER_TYPES; ++i) + nr += nv50->sampler_nr[i]; - if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB)) - nv50_vertprog_validate(nv50); + so = so_new(1 + 5 * PIPE_SHADER_TYPES, + 1 + 19 * PIPE_SHADER_TYPES + nr * 8, + PIPE_SHADER_TYPES * 2); - if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB)) - nv50_fragprog_validate(nv50); + nv50_validate_samplers(nv50, so, PIPE_SHADER_VERTEX); + nv50_validate_samplers(nv50, so, PIPE_SHADER_FRAGMENT); - if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB)) - nv50_geomprog_validate(nv50); + so_method(so, tesla, 0x1334, 1); /* flush TSC */ + so_data (so, 0); - if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | - NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER)) - nv50_fp_linkage_validate(nv50); + return so; +} - if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_VERTPROG)) - nv50_gp_linkage_validate(nv50); +static struct nouveau_stateobj * +validate_vtxbuf(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->state.vtxbuf, &so); + return so; +} - if (nv50->dirty & NV50_NEW_RASTERIZER) - so_ref(nv50->rasterizer->so, &nv50->state.rast); +static struct nouveau_stateobj * +validate_vtxattr(struct nv50_context *nv50) +{ + struct nouveau_stateobj *so = NULL; + so_ref(nv50->state.vtxattr, &so); + return so; +} - if (nv50->dirty & NV50_NEW_BLEND_COLOUR) { - so = so_new(1, 4, 0); - so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4); - so_data (so, fui(nv50->blend_colour.color[0])); - so_data (so, fui(nv50->blend_colour.color[1])); - so_data (so, fui(nv50->blend_colour.color[2])); - so_data (so, fui(nv50->blend_colour.color[3])); - so_ref(so, &nv50->state.blend_colour); - so_ref(NULL, &so); - } +struct state_validate { + struct nouveau_stateobj *(*func)(struct nv50_context *nv50); + unsigned states; +} validate_list[] = { + { validate_fb , NV50_NEW_FRAMEBUFFER }, + { validate_blend , NV50_NEW_BLEND }, + { validate_zsa , NV50_NEW_ZSA }, + { nv50_vertprog_validate , NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB }, + { nv50_fragprog_validate , NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB }, + { nv50_geomprog_validate , NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB }, + { nv50_fp_linkage_validate, NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG | + NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER }, + { nv50_gp_linkage_validate, NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG }, + { validate_rast , NV50_NEW_RASTERIZER }, + { validate_blend_colour , NV50_NEW_BLEND_COLOUR }, + { validate_stencil_ref , NV50_NEW_STENCIL_REF }, + { validate_stipple , NV50_NEW_STIPPLE }, + { validate_scissor , NV50_NEW_SCISSOR }, + { validate_viewport , NV50_NEW_VIEWPORT }, + { validate_sampler , NV50_NEW_SAMPLER }, + { nv50_tex_validate , NV50_NEW_TEXTURE | NV50_NEW_SAMPLER }, + { nv50_vbo_validate , NV50_NEW_ARRAYS }, + { validate_vtxbuf , NV50_NEW_ARRAYS }, + { validate_vtxattr , NV50_NEW_ARRAYS }, + {} +}; +#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0])) - if (nv50->dirty & NV50_NEW_STENCIL_REF) { - so = so_new(2, 2, 0); - so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 1); - so_data (so, nv50->stencil_ref.ref_value[0]); - so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 1); - so_data (so, nv50->stencil_ref.ref_value[1]); - so_ref(so, &nv50->state.stencil_ref); - so_ref(NULL, &so); - } +boolean +nv50_state_validate(struct nv50_context *nv50, unsigned wait_dwords) +{ + struct nouveau_channel *chan = nv50->screen->base.channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; + unsigned nr_relocs = 128, nr_dwords = wait_dwords + 128 + 4; + int ret, i; - if (nv50->dirty & NV50_NEW_STIPPLE) { - so = so_new(1, 32, 0); - so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32); - for (i = 0; i < 32; i++) - so_data(so, util_bswap32(nv50->stipple.stipple[i])); - so_ref(so, &nv50->state.stipple); - so_ref(NULL, &so); - } + for (i = 0; i < validate_list_len; i++) { + struct state_validate *validate = &validate_list[i]; + struct nouveau_stateobj *so; - if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) { - struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe; - struct pipe_scissor_state *s = &nv50->scissor; + if (!(nv50->dirty & validate->states)) + continue; - if (nv50->state.scissor && - (rast->scissor == 0 && nv50->state.scissor_enabled == 0)) - goto scissor_uptodate; - nv50->state.scissor_enabled = rast->scissor; + so = validate->func(nv50); + if (!so) + continue; - so = so_new(1, 2, 0); - so_method(so, tesla, NV50TCL_SCISSOR_HORIZ(0), 2); - if (nv50->state.scissor_enabled) { - so_data(so, (s->maxx << 16) | s->minx); - so_data(so, (s->maxy << 16) | s->miny); - } else { - so_data(so, (nv50->framebuffer.width << 16)); - so_data(so, (nv50->framebuffer.height << 16)); - } - so_ref(so, &nv50->state.scissor); - so_ref(NULL, &so); - nv50->state.dirty |= NV50_NEW_SCISSOR; - } -scissor_uptodate: - - if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) { - if (nv50->state.viewport && - !(nv50->dirty & NV50_NEW_VIEWPORT)) - goto viewport_uptodate; - - so = so_new(5, 9, 0); - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE_X(0), 3); - so_data (so, fui(nv50->viewport.translate[0])); - so_data (so, fui(nv50->viewport.translate[1])); - so_data (so, fui(nv50->viewport.translate[2])); - so_method(so, tesla, NV50TCL_VIEWPORT_SCALE_X(0), 3); - so_data (so, fui(nv50->viewport.scale[0])); - so_data (so, fui(nv50->viewport.scale[1])); - so_data (so, fui(nv50->viewport.scale[2])); - - so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); - so_data (so, 1); - /* 0x0000 = remove whole primitive only (xyz) - * 0x1018 = remove whole primitive only (xy), clamp z - * 0x1080 = clip primitive (xyz) - * 0x1098 = clip primitive (xy), clamp z - */ - so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); - so_data (so, 0x1080); - /* no idea what 0f90 does */ - so_method(so, tesla, 0x0f90, 1); - so_data (so, 0); + nr_dwords += (so->total + so->cur); + nr_relocs += so->cur_reloc; - so_ref(so, &nv50->state.viewport); + so_ref(so, &nv50->state.hw[i]); so_ref(NULL, &so); - nv50->state.dirty |= NV50_NEW_VIEWPORT; + nv50->state.hw_dirty |= (1 << i); } -viewport_uptodate: - - if (nv50->dirty & NV50_NEW_SAMPLER) { - unsigned nr = 0; - - for (i = 0; i < PIPE_SHADER_TYPES; ++i) - nr += nv50->sampler_nr[i]; + nv50->dirty = 0; - so = so_new(1 + 5 * PIPE_SHADER_TYPES, - 1 + 19 * PIPE_SHADER_TYPES + nr * 8, - PIPE_SHADER_TYPES * 2); + if (nv50->screen->cur_ctx != nv50) { + for (i = 0; i < validate_list_len; i++) { + if (!nv50->state.hw[i] || + (nv50->state.hw_dirty & (1 << i))) + continue; - nv50_validate_samplers(nv50, so, PIPE_SHADER_VERTEX); - nv50_validate_samplers(nv50, so, PIPE_SHADER_FRAGMENT); + nr_dwords += (nv50->state.hw[i]->total + + nv50->state.hw[i]->cur); + nr_relocs += nv50->state.hw[i]->cur_reloc; + nv50->state.hw_dirty |= (1 << i); + } - so_method(so, tesla, 0x1334, 1); /* flush TSC */ - so_data (so, 0); + nv50->screen->cur_ctx = nv50; + } - so_ref(so, &nv50->state.tsc_upload); - so_ref(NULL, &so); + ret = MARK_RING(chan, nr_dwords, nr_relocs); + if (ret) { + debug_printf("MARK_RING(%d, %d) failed: %d\n", + nr_dwords, nr_relocs, ret); + return FALSE; } - if (nv50->dirty & (NV50_NEW_TEXTURE | NV50_NEW_SAMPLER)) - nv50_tex_validate(nv50); + while (nv50->state.hw_dirty) { + i = ffs(nv50->state.hw_dirty) - 1; + nv50->state.hw_dirty &= ~(1 << i); - if (nv50->dirty & NV50_NEW_ARRAYS) - nv50_vbo_validate(nv50); + so_emit(chan, nv50->state.hw[i]); + } - nv50->state.dirty |= nv50->dirty; - nv50->dirty = 0; - nv50_state_emit(nv50); + /* Yes, really, we need to do this. If a buffer that is referenced + * on the hardware isn't part of changed state above, without doing + * this the kernel is given no clue that the buffer is being used + * still. This can cause all sorts of fun issues. + */ + nv50_tex_relocs(nv50); + so_emit_reloc_markers(chan, nv50->state.hw[0]); /* fb */ + so_emit_reloc_markers(chan, nv50->state.hw[3]); /* vp */ + so_emit_reloc_markers(chan, nv50->state.hw[4]); /* fp */ + so_emit_reloc_markers(chan, nv50->state.hw[17]); /* vb */ + so_emit_reloc_markers(chan, nv50->screen->static_init); + /* No idea.. */ + BEGIN_RING(chan, tesla, 0x142c, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, tesla, 0x142c, 1); + OUT_RING (chan, 0); return TRUE; } diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index de0560e20cd..4c48b12cd87 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -24,6 +24,7 @@ #include "nv50_texture.h" #include "nouveau/nouveau_stateobj.h" +#include "nouveau/nouveau_reloc.h" #include "util/u_format.h" @@ -195,6 +196,35 @@ nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so, } void +nv50_tex_relocs(struct nv50_context *nv50) +{ + struct nouveau_channel *chan = nv50->screen->tesla->channel; + int p, unit; + + p = PIPE_SHADER_FRAGMENT; + for (unit = 0; unit < nv50->miptree_nr[p]; unit++) { + if (!nv50->miptree[p][unit]) + continue; + nouveau_reloc_emit(chan, nv50->screen->tic, + ((p * 32) + unit) * 32, NULL, + nv50->miptree[p][unit]->base.bo, 0, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | + NOUVEAU_BO_RD, 0, 0); + } + + p = PIPE_SHADER_VERTEX; + for (unit = 0; unit < nv50->miptree_nr[p]; unit++) { + if (!nv50->miptree[p][unit]) + continue; + nouveau_reloc_emit(chan, nv50->screen->tic, + ((p * 32) + unit) * 32, NULL, + nv50->miptree[p][unit]->base.bo, 0, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | + NOUVEAU_BO_RD, 0, 0); + } +} + +struct nouveau_stateobj * nv50_tex_validate(struct nv50_context *nv50) { struct nouveau_stateobj *so; @@ -217,12 +247,11 @@ nv50_tex_validate(struct nv50_context *nv50) so_ref(NULL, &so); NOUVEAU_ERR("failed tex validate\n"); - return; + return NULL; } so_method(so, tesla, 0x1330, 1); /* flush TIC */ so_data (so, 0); - so_ref(so, &nv50->state.tic_upload); - so_ref(NULL, &so); + return so; } diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index 7c360e9e73a..9eb223eca65 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -121,11 +121,12 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, } static struct pipe_transfer * -nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +nv50_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, unsigned x, unsigned y, unsigned w, unsigned h) { + struct pipe_screen *pscreen = pcontext->screen; struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = nv50_miptree(pt); struct nv50_miptree_level *lvl = &mt->level[level]; @@ -186,7 +187,7 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } static void -nv50_transfer_del(struct pipe_transfer *ptx) +nv50_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; struct nv50_miptree *mt = nv50_miptree(ptx->texture); @@ -196,7 +197,7 @@ nv50_transfer_del(struct pipe_transfer *ptx) unsigned ny = util_format_get_nblocksy(pt->format, tx->base.height); if (ptx->usage & PIPE_TRANSFER_WRITE) { - struct pipe_screen *pscreen = pt->screen; + struct pipe_screen *pscreen = pcontext->screen; nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride, tx->bo->tile_mode, @@ -218,7 +219,7 @@ nv50_transfer_del(struct pipe_transfer *ptx) } static void * -nv50_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv50_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; unsigned flags = 0; @@ -236,7 +237,7 @@ nv50_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } static void -nv50_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv50_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; @@ -244,12 +245,12 @@ nv50_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) } void -nv50_transfer_init_screen_functions(struct pipe_screen *pscreen) +nv50_init_transfer_functions(struct nv50_context *nv50) { - pscreen->get_tex_transfer = nv50_transfer_new; - pscreen->tex_transfer_destroy = nv50_transfer_del; - pscreen->transfer_map = nv50_transfer_map; - pscreen->transfer_unmap = nv50_transfer_unmap; + nv50->pipe.get_tex_transfer = nv50_transfer_new; + nv50->pipe.tex_transfer_destroy = nv50_transfer_del; + nv50->pipe.transfer_map = nv50_transfer_map; + nv50->pipe.transfer_unmap = nv50_transfer_unmap; } void diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 1c8ee0b9adf..6b9c1ee231e 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -25,53 +25,9 @@ #include "util/u_inlines.h" #include "util/u_format.h" +#include "nouveau/nouveau_util.h" #include "nv50_context.h" -static boolean -nv50_push_elements_u08(struct nv50_context *, uint8_t *, unsigned); - -static boolean -nv50_push_elements_u16(struct nv50_context *, uint16_t *, unsigned); - -static boolean -nv50_push_elements_u32(struct nv50_context *, uint32_t *, unsigned); - -static boolean -nv50_push_arrays(struct nv50_context *, unsigned, unsigned); - -#define NV50_USING_LOATHED_EDGEFLAG(ctx) ((ctx)->vertprog->cfg.edgeflag_in < 16) - -static INLINE unsigned -nv50_prim(unsigned mode) -{ - switch (mode) { - case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS; - case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES; - case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP; - case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP; - case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES; - case PIPE_PRIM_TRIANGLE_STRIP: - return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP; - case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN; - case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS; - case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP; - case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON; - case PIPE_PRIM_LINES_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY; - case PIPE_PRIM_LINE_STRIP_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY; - case PIPE_PRIM_TRIANGLES_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY; - case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: - return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY; - default: - break; - } - - NOUVEAU_ERR("invalid primitive type %d\n", mode); - return NV50TCL_VERTEX_BEGIN_POINTS; -} - static INLINE uint32_t nv50_vbo_type_to_hw(enum pipe_format format) { @@ -139,15 +95,16 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) uint32_t hw_type, hw_size; enum pipe_format pf = ve->src_format; const struct util_format_description *desc; - unsigned size; + unsigned size, nr_components; desc = util_format_description(pf); assert(desc); size = util_format_get_component_bits(pf, UTIL_FORMAT_COLORSPACE_RGB, 0); + nr_components = util_format_get_nr_components(pf); hw_type = nv50_vbo_type_to_hw(pf); - hw_size = nv50_vbo_size_to_hw(size, ve->nr_components); + hw_size = nv50_vbo_size_to_hw(size, nr_components); if (!hw_type || !hw_size) { NOUVEAU_ERR("unsupported vbo format: %s\n", util_format_name(pf)); @@ -161,250 +118,58 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) return (hw_type | hw_size); } -/* For instanced drawing from user buffers, hitting the FIFO repeatedly - * with the same vertex data is probably worse than uploading all data. - */ -static boolean -nv50_upload_vtxbuf(struct nv50_context *nv50, unsigned i) -{ - struct nv50_screen *nscreen = nv50->screen; - struct pipe_screen *pscreen = &nscreen->base.base; - struct pipe_buffer *buf = nscreen->strm_vbuf[i]; - struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - uint8_t *src; - unsigned size = align(vb->buffer->size, 4096); - - if (buf && buf->size < size) - pipe_buffer_reference(&nscreen->strm_vbuf[i], NULL); - - if (!nscreen->strm_vbuf[i]) { - nscreen->strm_vbuf[i] = pipe_buffer_create( - pscreen, 0, PIPE_BUFFER_USAGE_VERTEX, size); - buf = nscreen->strm_vbuf[i]; - } - - src = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); - if (!src) - return FALSE; - src += vb->buffer_offset; - - size = (vb->max_index + 1) * vb->stride + 16; /* + 16 is for stride 0 */ - if (vb->buffer_offset + size > vb->buffer->size) - size = vb->buffer->size - vb->buffer_offset; - - pipe_buffer_write(pscreen, buf, vb->buffer_offset, size, src); - pipe_buffer_unmap(pscreen, vb->buffer); - - vb->buffer = buf; /* don't pipe_reference, this is a private copy */ - return TRUE; -} - -static void -nv50_upload_user_vbufs(struct nv50_context *nv50) -{ - unsigned i; - - if (nv50->vbo_fifo) - nv50->dirty |= NV50_NEW_ARRAYS; - if (!(nv50->dirty & NV50_NEW_ARRAYS)) - return; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) { - if (nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX) - continue; - nv50_upload_vtxbuf(nv50, i); - } -} - -static void -nv50_set_static_vtxattr(struct nv50_context *nv50, unsigned i, void *data) -{ - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; - float v[4]; - - util_format_read_4f(nv50->vtxelt[i].src_format, - v, 0, data, 0, 0, 0, 1, 1); - - switch (nv50->vtxelt[i].nr_components) { - case 4: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_4F_X(i), 4); - OUT_RINGf (chan, v[0]); - OUT_RINGf (chan, v[1]); - OUT_RINGf (chan, v[2]); - OUT_RINGf (chan, v[3]); - break; - case 3: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_3F_X(i), 3); - OUT_RINGf (chan, v[0]); - OUT_RINGf (chan, v[1]); - OUT_RINGf (chan, v[2]); - break; - case 2: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_2F_X(i), 2); - OUT_RINGf (chan, v[0]); - OUT_RINGf (chan, v[1]); - break; - case 1: - BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_1F(i), 1); - OUT_RINGf (chan, v[0]); - break; - default: - assert(0); - break; - } -} - -static unsigned -init_per_instance_arrays_immd(struct nv50_context *nv50, - unsigned startInstance, - unsigned pos[16], unsigned step[16]) -{ - struct nouveau_bo *bo; - unsigned i, b, count = 0; - - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) - continue; - ++count; - b = nv50->vtxelt[i].vertex_buffer_index; - - pos[i] = nv50->vtxelt[i].src_offset + - nv50->vtxbuf[b].buffer_offset + - startInstance * nv50->vtxbuf[b].stride; - step[i] = startInstance % nv50->vtxelt[i].instance_divisor; - - bo = nouveau_bo(nv50->vtxbuf[b].buffer); - if (!bo->map) - nouveau_bo_map(bo, NOUVEAU_BO_RD); - - nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); - } - - return count; -} - -static unsigned -init_per_instance_arrays(struct nv50_context *nv50, - unsigned startInstance, - unsigned pos[16], unsigned step[16]) -{ - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; +struct instance { struct nouveau_bo *bo; - struct nouveau_stateobj *so; - unsigned i, b, count = 0; - const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - - if (nv50->vbo_fifo) - return init_per_instance_arrays_immd(nv50, startInstance, - pos, step); - - so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); - - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) - continue; - ++count; - b = nv50->vtxelt[i].vertex_buffer_index; - - pos[i] = nv50->vtxelt[i].src_offset + - nv50->vtxbuf[b].buffer_offset + - startInstance * nv50->vtxbuf[b].stride; - - if (!startInstance) { - step[i] = 0; - continue; - } - step[i] = startInstance % nv50->vtxelt[i].instance_divisor; - - bo = nouveau_bo(nv50->vtxbuf[b].buffer); - - so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); - } - - if (count && startInstance) { - so_ref (so, &nv50->state.instbuf); /* for flush notify */ - so_emit(chan, nv50->state.instbuf); - } - so_ref (NULL, &so); - - return count; -} + unsigned delta; + unsigned stride; + unsigned step; + unsigned divisor; +}; static void -step_per_instance_arrays_immd(struct nv50_context *nv50, - unsigned pos[16], unsigned step[16]) +instance_init(struct nv50_context *nv50, struct instance *a, unsigned first) { - struct nouveau_bo *bo; - unsigned i, b; + int i; - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) - continue; - if (++step[i] != nv50->vtxelt[i].instance_divisor) - continue; - b = nv50->vtxelt[i].vertex_buffer_index; - bo = nouveau_bo(nv50->vtxbuf[b].buffer); + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; + struct pipe_vertex_buffer *vb; - step[i] = 0; - pos[i] += nv50->vtxbuf[b].stride; + a[i].divisor = ve->instance_divisor; + if (a[i].divisor) { + vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); + a[i].bo = nouveau_bo(vb->buffer); + a[i].stride = vb->stride; + a[i].step = first % a[i].divisor; + a[i].delta = vb->buffer_offset + ve->src_offset + + (first * a[i].stride); + } } } static void -step_per_instance_arrays(struct nv50_context *nv50, - unsigned pos[16], unsigned step[16]) +instance_step(struct nv50_context *nv50, struct instance *a) { + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; - struct nouveau_bo *bo; - struct nouveau_stateobj *so; - unsigned i, b; - const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - - if (nv50->vbo_fifo) { - step_per_instance_arrays_immd(nv50, pos, step); - return; - } - - so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); + int i; - for (i = 0; i < nv50->vtxelt_nr; ++i) { - if (!nv50->vtxelt[i].instance_divisor) + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + if (!a[i].divisor) continue; - b = nv50->vtxelt[i].vertex_buffer_index; - if (++step[i] == nv50->vtxelt[i].instance_divisor) { - step[i] = 0; - pos[i] += nv50->vtxbuf[b].stride; + BEGIN_RING(chan, tesla, + NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); + OUT_RELOCh(chan, a[i].bo, a[i].delta, NOUVEAU_BO_RD | + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); + OUT_RELOCl(chan, a[i].bo, a[i].delta, NOUVEAU_BO_RD | + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); + if (++a[i].step == a[i].divisor) { + a[i].step = 0; + a[i].delta += a[i].stride; } - - bo = nouveau_bo(nv50->vtxbuf[b].buffer); - - so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); } - - so_ref (so, &nv50->state.instbuf); /* for flush notify */ - so_ref (NULL, &so); - - so_emit(chan, nv50->state.instbuf); -} - -static INLINE void -nv50_unmap_vbufs(struct nv50_context *nv50) -{ - unsigned i; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) - if (nouveau_bo(nv50->vtxbuf[i].buffer)->map) - nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); } void @@ -415,198 +180,207 @@ nv50_draw_arrays_instanced(struct pipe_context *pipe, struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - unsigned i, nz_divisors; - unsigned step[16], pos[16]; - - if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) - nv50_upload_user_vbufs(nv50); + struct instance a[16]; + unsigned prim = nv50_prim(mode); - nv50_state_validate(nv50); + instance_init(nv50, a, startInstance); + if (!nv50_state_validate(nv50, 10 + 16*3)) + return; - nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + if (nv50->vbo_fifo) { + nv50_push_elements_instanced(pipe, NULL, 0, mode, start, + count, startInstance, + instanceCount); + return; + } BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); OUT_RING (chan, NV50_CB_AUX | (24 << 8)); OUT_RING (chan, startInstance); + while (instanceCount--) { + if (AVAIL_RING(chan) < (7 + 16*3)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, 7 + 16*3)) { + assert(0); + return; + } + } + instance_step(nv50, a); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - if (nv50->vbo_fifo) - nv50_push_arrays(nv50, start, count); - else { + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, prim); BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); OUT_RING (chan, start); OUT_RING (chan, count); - } - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); - - for (i = 1; i < instanceCount; i++) { - if (nz_divisors) /* any non-zero array divisors ? */ - step_per_instance_arrays(nv50, pos, step); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode) | (1 << 28)); - - if (nv50->vbo_fifo) - nv50_push_arrays(nv50, start, count); - else { - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); - OUT_RING (chan, start); - OUT_RING (chan, count); - } BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); - } - nv50_unmap_vbufs(nv50); - so_ref(NULL, &nv50->state.instbuf); + prim |= (1 << 28); + } } void nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - boolean ret; - - nv50_state_validate(nv50); - - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - if (nv50->vbo_fifo) - ret = nv50_push_arrays(nv50, start, count); - else { - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); - OUT_RING (chan, start); - OUT_RING (chan, count); - ret = TRUE; - } - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); - - nv50_unmap_vbufs(nv50); - - /* XXX: not sure what to do if ret != TRUE: flush and retry? - */ - assert(ret); + nv50_draw_arrays_instanced(pipe, mode, start, count, 0, 1); } -static INLINE boolean -nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map, - unsigned start, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - - map += start; +struct inline_ctx { + struct nv50_context *nv50; + void *map; +}; - if (nv50->vbo_fifo) - return nv50_push_elements_u08(nv50, map, count); +static void +inline_elt08(void *priv, unsigned start, unsigned count) +{ + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + uint8_t *map = (uint8_t *)ctx->map + start; if (count & 1) { BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, map[0]); map++; - count--; + count &= ~1; } - while (count) { - unsigned nr = count > 2046 ? 2046 : count; - int i; - - BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); - for (i = 0; i < nr; i += 2) - OUT_RING (chan, (map[i + 1] << 16) | map[i]); + count >>= 1; + if (!count) + return; - count -= nr; - map += nr; + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, count); + while (count--) { + OUT_RING(chan, (map[1] << 16) | map[0]); + map += 2; } - return TRUE; } -static INLINE boolean -nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, - unsigned start, unsigned count) +static void +inline_elt16(void *priv, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - - map += start; - - if (nv50->vbo_fifo) - return nv50_push_elements_u16(nv50, map, count); + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + uint16_t *map = (uint16_t *)ctx->map + start; if (count & 1) { BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, map[0]); + count &= ~1; map++; - count--; } - while (count) { - unsigned nr = count > 2046 ? 2046 : count; - int i; - - BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); - for (i = 0; i < nr; i += 2) - OUT_RING (chan, (map[i + 1] << 16) | map[i]); + count >>= 1; + if (!count) + return; - count -= nr; - map += nr; + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, count); + while (count--) { + OUT_RING(chan, (map[1] << 16) | map[0]); + map += 2; } - return TRUE; } -static INLINE boolean -nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, - unsigned start, unsigned count) +static void +inline_elt32(void *priv, unsigned start, unsigned count) +{ + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U32, count); + OUT_RINGp (chan, (uint32_t *)ctx->map + start, count); +} + +static void +inline_edgeflag(void *priv, boolean enabled) { + struct inline_ctx *ctx = priv; + struct nouveau_grobj *tesla = ctx->nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + + BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, enabled ? 1 : 0); +} + +static void +nv50_draw_elements_inline(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, unsigned indexSize, + unsigned mode, unsigned start, unsigned count, + unsigned startInstance, unsigned instanceCount) +{ + struct pipe_screen *pscreen = pipe->screen; + struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; + struct instance a[16]; + struct inline_ctx ctx; + struct u_split_prim s; + boolean nzi = FALSE; + unsigned overhead; + + overhead = 16*3; /* potential instance adjustments */ + overhead += 4; /* Begin()/End() */ + overhead += 4; /* potential edgeflag disable/reenable */ + overhead += 3; /* potentially 3 VTX_ELT_U16/U32 packet headers */ + + s.priv = &ctx; + if (indexSize == 1) + s.emit = inline_elt08; + else + if (indexSize == 2) + s.emit = inline_elt16; + else + s.emit = inline_elt32; + s.edge = inline_edgeflag; + + ctx.nv50 = nv50; + ctx.map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + assert(ctx.map); + if (!ctx.map) + return; - map += start; + instance_init(nv50, a, startInstance); + if (!nv50_state_validate(nv50, overhead + 6 + 3)) + return; - if (nv50->vbo_fifo) - return nv50_push_elements_u32(nv50, map, count); + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, startInstance); + while (instanceCount--) { + unsigned max_verts; + boolean done; + + u_split_prim_init(&s, mode, start, count); + do { + if (AVAIL_RING(chan) < (overhead + 6)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, (overhead + 6))) { + assert(0); + return; + } + } - while (count) { - unsigned nr = count > 2047 ? 2047 : count; + max_verts = AVAIL_RING(chan) - overhead; + if (max_verts > 2047) + max_verts = 2047; + if (indexSize != 4) + max_verts <<= 1; + instance_step(nv50, a); - BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U32, nr); - OUT_RINGp (chan, map, nr); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(s.mode) | (nzi ? (1<<28) : 0)); + done = u_split_prim_next(&s, max_verts); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } while (!done); - count -= nr; - map += nr; + nzi = TRUE; } - return TRUE; -} -static INLINE void -nv50_draw_elements_inline(struct nv50_context *nv50, - void *map, unsigned indexSize, - unsigned start, unsigned count) -{ - switch (indexSize) { - case 1: - nv50_draw_elements_inline_u08(nv50, map, start, count); - break; - case 2: - nv50_draw_elements_inline_u16(nv50, map, start, count); - break; - case 4: - nv50_draw_elements_inline_u32(nv50, map, start, count); - break; - } + pipe_buffer_unmap(pscreen, indexBuffer); } void @@ -617,49 +391,68 @@ nv50_draw_elements_instanced(struct pipe_context *pipe, unsigned startInstance, unsigned instanceCount) { struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_channel *chan = tesla->channel; - struct pipe_screen *pscreen = pipe->screen; - void *map; - unsigned i, nz_divisors; - unsigned step[16], pos[16]; + struct instance a[16]; + unsigned prim = nv50_prim(mode); - map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); - - if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) - nv50_upload_user_vbufs(nv50); - - nv50_state_validate(nv50); + instance_init(nv50, a, startInstance); + if (!nv50_state_validate(nv50, 13 + 16*3)) + return; - nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + if (nv50->vbo_fifo) { + nv50_push_elements_instanced(pipe, indexBuffer, indexSize, + mode, start, count, startInstance, + instanceCount); + return; + } else + if (!(indexBuffer->usage & PIPE_BUFFER_USAGE_INDEX) || indexSize == 1) { + nv50_draw_elements_inline(pipe, indexBuffer, indexSize, + mode, start, count, startInstance, + instanceCount); + return; + } BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); OUT_RING (chan, NV50_CB_AUX | (24 << 8)); OUT_RING (chan, startInstance); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - nv50_draw_elements_inline(nv50, map, indexSize, start, count); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); - - for (i = 1; i < instanceCount; ++i) { - if (nz_divisors) /* any non-zero array divisors ? */ - step_per_instance_arrays(nv50, pos, step); + while (instanceCount--) { + if (AVAIL_RING(chan) < (7 + 16*3)) { + FIRE_RING(chan); + if (!nv50_state_validate(nv50, 10 + 16*3)) { + assert(0); + return; + } + } + instance_step(nv50, a); BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode) | (1 << 28)); - - nv50_draw_elements_inline(nv50, map, indexSize, start, count); - + OUT_RING (chan, prim); + if (indexSize == 4) { + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x30000, 0); + OUT_RING (chan, count); + nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), + start << 2, count << 2); + } else + if (indexSize == 2) { + unsigned vb_start = (start & ~1); + unsigned vb_end = (start + count + 1) & ~1; + unsigned dwords = (vb_end - vb_start) >> 1; + + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); + OUT_RING (chan, ((start & 1) << 31) | count); + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x30000, 0); + OUT_RING (chan, dwords); + nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), + vb_start << 1, dwords << 2); + BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); + OUT_RING (chan, 0); + } BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); - } - nv50_unmap_vbufs(nv50); - so_ref(NULL, &nv50->state.instbuf); + prim |= (1 << 28); + } } void @@ -667,51 +460,8 @@ nv50_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { - struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->tesla->channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct pipe_screen *pscreen = pipe->screen; - void *map; - - nv50_state_validate(nv50); - - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, tesla, 0x142c, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); - OUT_RING (chan, nv50_prim(mode)); - - if (!nv50->vbo_fifo && indexSize == 4) { - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x30000, 0); - OUT_RING (chan, count); - nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), - start << 2, count << 2); - } else - if (!nv50->vbo_fifo && indexSize == 2) { - unsigned vb_start = (start & ~1); - unsigned vb_end = (start + count + 1) & ~1; - unsigned dwords = (vb_end - vb_start) >> 1; - - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); - OUT_RING (chan, ((start & 1) << 31) | count); - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x30000, 0); - OUT_RING (chan, dwords); - nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), - vb_start << 1, dwords << 2); - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); - OUT_RING (chan, 0); - } else { - map = pipe_buffer_map(pscreen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - nv50_draw_elements_inline(nv50, map, indexSize, start, count); - nv50_unmap_vbufs(nv50); - pipe_buffer_unmap(pscreen, indexBuffer); - } - - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); - OUT_RING (chan, 0); + nv50_draw_elements_instanced(pipe, indexBuffer, indexSize, + mode, start, count, 0, 1); } static INLINE boolean @@ -726,6 +476,7 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, struct nouveau_bo *bo = nouveau_bo(vb->buffer); float v[4]; int ret; + unsigned nr_components = util_format_get_nr_components(ve->src_format); ret = nouveau_bo_map(bo, NOUVEAU_BO_RD); if (ret) @@ -736,9 +487,10 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, 0, 0, 1, 1); so = *pso; if (!so) - *pso = so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 4, 0); + *pso = so = so_new(nv50->vtxelt->num_elements, + nv50->vtxelt->num_elements * 4, 0); - switch (ve->nr_components) { + switch (nr_components) { case 4: so_method(so, tesla, NV50TCL_VTX_ATTR_4F_X(attrib), 4); so_data (so, fui(v[0])); @@ -775,6 +527,18 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, } void +nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso) +{ + unsigned i; + + for (i = 0; i < cso->num_elements; ++i) { + struct pipe_vertex_element *ve = &cso->pipe[i]; + + cso->hw[i] = nv50_vbo_vtxelt_to_hw(ve); + } +} + +struct nouveau_stateobj * nv50_vbo_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -783,30 +547,31 @@ nv50_vbo_validate(struct nv50_context *nv50) /* don't validate if Gallium took away our buffers */ if (nv50->vtxbuf_nr == 0) - return; - nv50->vbo_fifo = 0; + return NULL; + + if (nv50->screen->force_push || + nv50->vertprog->cfg.edgeflag_in < 16) + nv50->vbo_fifo = 0xffff; - for (i = 0; i < nv50->vtxbuf_nr; ++i) + for (i = 0; i < nv50->vtxbuf_nr; i++) { if (nv50->vtxbuf[i].stride && !(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX)) nv50->vbo_fifo = 0xffff; + } - if (NV50_USING_LOATHED_EDGEFLAG(nv50)) - nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */ - - n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr); + n_ve = MAX2(nv50->vtxelt->num_elements, nv50->state.vtxelt_nr); vtxattr = NULL; - vtxbuf = so_new(n_ve * 2, n_ve * 5, nv50->vtxelt_nr * 4); + vtxbuf = so_new(n_ve * 2, n_ve * 5, nv50->vtxelt->num_elements * 4); vtxfmt = so_new(1, n_ve, 0); so_method(vtxfmt, tesla, NV50TCL_VERTEX_ARRAY_ATTRIB(0), n_ve); - for (i = 0; i < nv50->vtxelt_nr; i++) { - struct pipe_vertex_element *ve = &nv50->vtxelt[i]; + for (i = 0; i < nv50->vtxelt->num_elements; i++) { + struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; struct nouveau_bo *bo = nouveau_bo(vb->buffer); - uint32_t hw = nv50_vbo_vtxelt_to_hw(ve); + uint32_t hw = nv50->vtxelt->hw[i]; if (!vb->stride && nv50_vbo_static_attrib(nv50, i, &vtxattr, ve, vb)) { @@ -821,13 +586,13 @@ nv50_vbo_validate(struct nv50_context *nv50) } if (nv50->vbo_fifo) { - so_data (vtxfmt, hw | - (ve->instance_divisor ? (1 << 4) : i)); + so_data (vtxfmt, hw | (ve->instance_divisor ? (1 << 4) : i)); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); so_data (vtxbuf, 0); continue; } + so_data(vtxfmt, hw | i); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3); @@ -855,355 +620,13 @@ nv50_vbo_validate(struct nv50_context *nv50) so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); so_data (vtxbuf, 0); } - nv50->state.vtxelt_nr = nv50->vtxelt_nr; + nv50->state.vtxelt_nr = nv50->vtxelt->num_elements; - so_ref (vtxfmt, &nv50->state.vtxfmt); so_ref (vtxbuf, &nv50->state.vtxbuf); so_ref (vtxattr, &nv50->state.vtxattr); so_ref (NULL, &vtxbuf); - so_ref (NULL, &vtxfmt); so_ref (NULL, &vtxattr); + return vtxfmt; } -typedef void (*pfn_push)(struct nouveau_channel *, void *); - -struct nv50_vbo_emitctx -{ - pfn_push push[16]; - uint8_t *map[16]; - unsigned stride[16]; - unsigned nr_ve; - unsigned vtx_dwords; - unsigned vtx_max; - - float edgeflag; - unsigned ve_edgeflag; -}; - -static INLINE void -emit_vtx_next(struct nouveau_channel *chan, struct nv50_vbo_emitctx *emit) -{ - unsigned i; - - for (i = 0; i < emit->nr_ve; ++i) { - emit->push[i](chan, emit->map[i]); - emit->map[i] += emit->stride[i]; - } -} - -static INLINE void -emit_vtx(struct nouveau_channel *chan, struct nv50_vbo_emitctx *emit, - uint32_t vi) -{ - unsigned i; - - for (i = 0; i < emit->nr_ve; ++i) - emit->push[i](chan, emit->map[i] + emit->stride[i] * vi); -} - -static INLINE boolean -nv50_map_vbufs(struct nv50_context *nv50) -{ - int i; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) { - struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - unsigned size = vb->stride * (vb->max_index + 1) + 16; - - if (nouveau_bo(vb->buffer)->map) - continue; - - size = vb->stride * (vb->max_index + 1) + 16; - size = MIN2(size, vb->buffer->size); - if (!size) - size = vb->buffer->size; - - if (nouveau_bo_map_range(nouveau_bo(vb->buffer), - 0, size, NOUVEAU_BO_RD)) - break; - } - - if (i == nv50->vtxbuf_nr) - return TRUE; - for (; i >= 0; --i) - nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); - return FALSE; -} - -static void -emit_b32_1(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); -} - -static void -emit_b32_2(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); - OUT_RING(chan, v[1]); -} - -static void -emit_b32_3(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); - OUT_RING(chan, v[1]); - OUT_RING(chan, v[2]); -} - -static void -emit_b32_4(struct nouveau_channel *chan, void *data) -{ - uint32_t *v = data; - - OUT_RING(chan, v[0]); - OUT_RING(chan, v[1]); - OUT_RING(chan, v[2]); - OUT_RING(chan, v[3]); -} - -static void -emit_b16_1(struct nouveau_channel *chan, void *data) -{ - uint16_t *v = data; - - OUT_RING(chan, v[0]); -} - -static void -emit_b16_3(struct nouveau_channel *chan, void *data) -{ - uint16_t *v = data; - - OUT_RING(chan, (v[1] << 16) | v[0]); - OUT_RING(chan, v[2]); -} - -static void -emit_b08_1(struct nouveau_channel *chan, void *data) -{ - uint8_t *v = data; - - OUT_RING(chan, v[0]); -} - -static void -emit_b08_3(struct nouveau_channel *chan, void *data) -{ - uint8_t *v = data; - - OUT_RING(chan, (v[2] << 16) | (v[1] << 8) | v[0]); -} - -static boolean -emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, - unsigned start) -{ - unsigned i; - - if (nv50_map_vbufs(nv50) == FALSE) - return FALSE; - - emit->ve_edgeflag = nv50->vertprog->cfg.edgeflag_in; - - emit->edgeflag = 0.5f; - emit->nr_ve = 0; - emit->vtx_dwords = 0; - - for (i = 0; i < nv50->vtxelt_nr; ++i) { - struct pipe_vertex_element *ve; - struct pipe_vertex_buffer *vb; - unsigned n, size; - const struct util_format_description *desc; - - ve = &nv50->vtxelt[i]; - vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - if (!(nv50->vbo_fifo & (1 << i)) || ve->instance_divisor) - continue; - n = emit->nr_ve++; - - emit->stride[n] = vb->stride; - emit->map[n] = (uint8_t *)nouveau_bo(vb->buffer)->map + - vb->buffer_offset + - (start * vb->stride + ve->src_offset); - - desc = util_format_description(ve->src_format); - assert(desc); - - size = util_format_get_component_bits( - ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0); - - assert(ve->nr_components > 0 && ve->nr_components <= 4); - - /* It shouldn't be necessary to push the implicit 1s - * for case 3 and size 8 cases 1, 2, 3. - */ - switch (size) { - default: - NOUVEAU_ERR("unsupported vtxelt size: %u\n", size); - return FALSE; - case 32: - switch (ve->nr_components) { - case 1: emit->push[n] = emit_b32_1; break; - case 2: emit->push[n] = emit_b32_2; break; - case 3: emit->push[n] = emit_b32_3; break; - case 4: emit->push[n] = emit_b32_4; break; - } - emit->vtx_dwords += ve->nr_components; - break; - case 16: - switch (ve->nr_components) { - case 1: emit->push[n] = emit_b16_1; break; - case 2: emit->push[n] = emit_b32_1; break; - case 3: emit->push[n] = emit_b16_3; break; - case 4: emit->push[n] = emit_b32_2; break; - } - emit->vtx_dwords += (ve->nr_components + 1) >> 1; - break; - case 8: - switch (ve->nr_components) { - case 1: emit->push[n] = emit_b08_1; break; - case 2: emit->push[n] = emit_b16_1; break; - case 3: emit->push[n] = emit_b08_3; break; - case 4: emit->push[n] = emit_b32_1; break; - } - emit->vtx_dwords += 1; - break; - } - } - - emit->vtx_max = 512 / emit->vtx_dwords; - if (emit->ve_edgeflag < 16) - emit->vtx_max = 1; - - return TRUE; -} - -static INLINE void -set_edgeflag(struct nouveau_channel *chan, - struct nouveau_grobj *tesla, - struct nv50_vbo_emitctx *emit, uint32_t index) -{ - unsigned i = emit->ve_edgeflag; - - if (i < 16) { - float f = *((float *)(emit->map[i] + index * emit->stride[i])); - - if (emit->edgeflag != f) { - emit->edgeflag = f; - - BEGIN_RING(chan, tesla, 0x15e4, 1); - OUT_RING (chan, f ? 1 : 0); - } - } -} - -static boolean -nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - if (emit_prepare(nv50, &emit, start) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */ - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx_next(chan, &emit); - - count -= nr; - } - - return TRUE; -} - -static boolean -nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - - if (emit_prepare(nv50, &emit, 0) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, *map); - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx(chan, &emit, *map++); - - count -= nr; - } - - return TRUE; -} - -static boolean -nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - - if (emit_prepare(nv50, &emit, 0) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, *map); - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx(chan, &emit, *map++); - - count -= nr; - } - - return TRUE; -} - -static boolean -nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count) -{ - struct nouveau_channel *chan = nv50->screen->base.channel; - struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nv50_vbo_emitctx emit; - - if (emit_prepare(nv50, &emit, 0) == FALSE) - return FALSE; - - while (count) { - unsigned i, dw, nr = MIN2(count, emit.vtx_max); - dw = nr * emit.vtx_dwords; - - set_edgeflag(chan, tesla, &emit, *map); - - BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); - for (i = 0; i < nr; ++i) - emit_vtx(chan, &emit, *map++); - - count -= nr; - } - - return TRUE; -} diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 1f69daec819..61b54af4ddf 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -19,7 +19,8 @@ C_SOURCES = \ r300_state_invariant.c \ r300_vs.c \ r300_texture.c \ - r300_tgsi_to_rc.c + r300_tgsi_to_rc.c \ + r300_transfer.c LIBRARY_INCLUDES = \ -I$(TOP)/src/mesa/drivers/dri/r300/compiler \ diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index 183aa17f9b3..27b2e309932 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -30,6 +30,7 @@ r300 = env.ConvenienceLibrary( 'r300_vs.c', 'r300_texture.c', 'r300_tgsi_to_rc.c', + 'r300_transfer.c', ] + r300compiler) + r300compiler Export('r300') diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 513cc0f5d44..b7ad6b20206 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -36,6 +36,7 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, &r300->clip); + util_blitter_save_vertex_elements(r300->blitter, r300->velems); } /* Clear currently bound buffers. */ diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 86b98a4ba52..8606c0004e5 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -34,6 +34,7 @@ #include "r300_screen.h" #include "r300_state_invariant.h" #include "r300_texture.h" +#include "r300_transfer.h" #include "radeon_winsys.h" @@ -60,7 +61,6 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->rs_block_state.state); FREE(r300->scissor_state.state); FREE(r300->textures_state.state); - FREE(r300->vertex_stream_state.state); FREE(r300->vap_output_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); @@ -72,11 +72,8 @@ r300_is_texture_referenced(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level) { - struct pipe_buffer* buf = 0; - - r300_get_texture_buffer(pipe->screen, texture, &buf, NULL); - - return pipe->is_buffer_referenced(pipe, buf); + return pipe->is_buffer_referenced(pipe, + ((struct r300_texture *)texture)->buffer); } static unsigned int @@ -86,7 +83,14 @@ r300_is_buffer_referenced(struct pipe_context *pipe, /* This only checks to see whether actual hardware buffers are * referenced. Since we use managed BOs and transfers, it's actually not * possible for pipe_buffers to ever reference the actual hardware, so - * buffers are never referenced. */ + * buffers are never referenced. + */ + + /* XXX: that doesn't make sense given that + * r300_is_texture_referenced is implemented on top of this + * function and hardware can certainly refer to textures + * directly... + */ return 0; } @@ -143,7 +147,6 @@ static void r300_setup_atoms(struct r300_context* r300) r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); r300->textures_state.state = CALLOC_STRUCT(r300_textures_state); - r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state); r300->vap_output_state.state = CALLOC_STRUCT(r300_vap_output_state); r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); @@ -159,6 +162,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300) return NULL; + r300screen->ctx = (struct pipe_context*)r300; + r300->winsys = radeon_winsys; r300->context.winsys = (struct pipe_winsys*)radeon_winsys; @@ -205,6 +210,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_query_functions(r300); + r300_init_transfer_functions(r300); + /* r300_init_surface_functions(r300); */ r300_init_state_functions(r300); @@ -212,7 +219,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->invariant_state.dirty = TRUE; r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); - r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw++; r300->blitter = util_blitter_create(&r300->context); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 0d1518a05bc..03b09603c72 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -124,13 +124,15 @@ struct r300_texture_format_state { uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */ }; +#define R300_MAX_TEXTURE_LEVELS 13 + struct r300_texture_fb_state { /* Colorbuffer. */ - uint32_t colorpitch[PIPE_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/ + uint32_t colorpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/ uint32_t us_out_fmt; /* R300_US_OUT_FMT[0-3] */ /* Zbuffer. */ - uint32_t depthpitch[PIPE_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */ + uint32_t depthpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */ uint32_t zb_format; /* R300_ZB_FORMAT */ }; @@ -236,16 +238,16 @@ struct r300_texture { struct pipe_texture tex; /* Offsets into the buffer. */ - unsigned offset[PIPE_MAX_TEXTURE_LEVELS]; + unsigned offset[R300_MAX_TEXTURE_LEVELS]; /* A pitch for each mip-level */ - unsigned pitch[PIPE_MAX_TEXTURE_LEVELS]; + unsigned pitch[R300_MAX_TEXTURE_LEVELS]; /* Size of one zslice or face based on the texture target */ - unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS]; + unsigned layer_size[R300_MAX_TEXTURE_LEVELS]; /* Whether the mipmap level is macrotiled. */ - enum r300_buffer_tiling mip_macrotile[PIPE_MAX_TEXTURE_LEVELS]; + enum r300_buffer_tiling mip_macrotile[R300_MAX_TEXTURE_LEVELS]; /** * If non-zero, override the natural texture layout with @@ -276,6 +278,23 @@ struct r300_texture { enum r300_buffer_tiling microtile, macrotile; }; +struct r300_vertex_info { + /* Parent class */ + struct vertex_info vinfo; + + /* R300_VAP_PROG_STREAK_CNTL_[0-7] */ + uint32_t vap_prog_stream_cntl[8]; + /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */ + uint32_t vap_prog_stream_cntl_ext[8]; +}; + +struct r300_vertex_element_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; + + struct r300_vertex_stream_state vertex_stream; +}; + extern struct pipe_viewport_state r300_viewport_identity; struct r300_context { @@ -348,8 +367,7 @@ struct r300_context { int vertex_buffer_count; int vertex_buffer_max_index; /* Vertex elements for Gallium. */ - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; - int vertex_element_count; + struct r300_vertex_element_state *velems; /* Vertex info for Draw. */ struct vertex_info vertex_info; @@ -368,6 +386,8 @@ struct r300_context { boolean polygon_offset_enabled; /* Z buffer bit depth. */ uint32_t zbuffer_bpp; + /* Whether scissor is enabled. */ + boolean scissor_enabled; }; /* Convenience cast wrapper. */ @@ -384,6 +404,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_state_functions(struct r300_context* r300); void r300_init_surface_functions(struct r300_context* r300); +void r300_init_tex_functions( struct pipe_context *pipe ); static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index addb28bded3..55e9217fd32 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -675,7 +675,7 @@ void r300_emit_scissor_state(struct r300_context* r300, maxx = fb->width; maxy = fb->height; - if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) { + if (r300->scissor_enabled) { minx = MAX2(minx, scissor->minx); miny = MAX2(miny, scissor->miny); maxx = MIN2(maxx, scissor->maxx); @@ -757,9 +757,9 @@ void r300_emit_textures_state(struct r300_context *r300, void r300_emit_aos(struct r300_context* r300, unsigned offset) { struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_vertex_element *velem = r300->velems->velem; int i; - unsigned size1, size2, aos_count = r300->vertex_element_count; + unsigned size1, size2, aos_count = r300->velems->count; unsigned packet_size = (aos_count * 3 + 1) / 2; CS_LOCALS(r300); @@ -794,6 +794,30 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) END_CS; } +void r300_emit_vertex_buffer(struct r300_context* r300) +{ + CS_LOCALS(r300); + + DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, " + "vertex size %d\n", r300->vbo, + r300->vertex_info.size); + /* Set the pointer to our vertex buffer. The emitted values are this: + * PACKET3 [3D_LOAD_VBPNTR] + * COUNT [1] + * FORMAT [size | stride << 8] + * OFFSET [offset into BO] + * VBPNTR [relocated BO] + */ + BEGIN_CS(7); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); + OUT_CS(1); + OUT_CS(r300->vertex_info.size | + (r300->vertex_info.size << 8)); + OUT_CS(r300->vbo_offset); + OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); + END_CS; +} + void r300_emit_vertex_stream_state(struct r300_context* r300, unsigned size, void* state) { @@ -868,7 +892,7 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) CS_LOCALS(r300); if (!r300screen->caps->has_tcl) { - debug_printf("r300: Implementation error: emit_vertex_shader called," + debug_printf("r300: Implementation error: emit_vs_state called," " but has_tcl is FALSE!\n"); return; } @@ -907,7 +931,7 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300, CS_LOCALS(r300); if (!r300screen->caps->has_tcl) { - debug_printf("r300: Implementation error: emit_vertex_shader called," + debug_printf("r300: Implementation error: emit_vs_constant_buffer called," " but has_tcl is FALSE!\n"); return; } @@ -980,7 +1004,7 @@ void r300_emit_buffer_validate(struct r300_context *r300, (struct r300_textures_state*)r300->textures_state.state; struct r300_texture* tex; struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_vertex_element *velem = r300->velems->velem; struct pipe_buffer *pbuf; unsigned i; boolean invalid = FALSE; @@ -1038,7 +1062,7 @@ validate: } /* ...vertex buffers for HWTCL path... */ if (do_validate_vertex_buffers) { - for (i = 0; i < r300->vertex_element_count; i++) { + for (i = 0; i < r300->velems->count; i++) { pbuf = vbuf[velem[i].vertex_buffer_index].buffer; if (!r300->winsys->add_buffer(r300->winsys, pbuf, @@ -1135,8 +1159,10 @@ void r300_emit_dirty_state(struct r300_context* r300) assert(r300->dirty_state == 0); */ - /* Finally, emit the VBO. */ - /* r300_emit_vertex_buffer(r300); */ + /* Emit the VBO for SWTCL. */ + if (!r300screen->caps->has_tcl) { + r300_emit_vertex_buffer(r300); + } r300->dirty_hw++; } diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index e37d3092703..70de152713d 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -61,6 +61,12 @@ static void r300_flush(struct pipe_context* pipe, atom->dirty = TRUE; } } + + /* Unmark HWTCL state for SWTCL. */ + if (!r300_screen(pipe->screen)->caps->has_tcl) { + r300->vs_state.dirty = FALSE; + r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS; + } } /* reset flushed query */ diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 3c2625269b8..9e71e61c303 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -207,6 +207,7 @@ static void r300_translate_fragment_shader( DBG(r300, DBG_FP, "r300: Error compiling fragment program: %s\n", compiler.Base.ErrorMsg); assert(0); + abort(); } /* And, finally... */ diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 6c891029a56..ef1b7510e18 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -143,7 +143,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; - unsigned vertex_element_count = r300->vertex_element_count; + unsigned vertex_element_count = r300->velems->count; unsigned i, v, vbi, dw, elem_offset, dwords; /* Size of the vertex, in dwords. */ @@ -166,7 +166,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { - velem = &r300->vertex_element[i]; + velem = &r300->velems->velem[i]; offset[i] = velem->src_offset / 4; size[i] = util_format_get_blocksize(velem->src_format) / 4; vertex_size += size[i]; @@ -183,18 +183,19 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, } } - dwords = 10 + count * vertex_size; + dwords = 9 + count * vertex_size; r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); - r300_emit_buffer_validate(r300, FALSE, 0); + r300_emit_buffer_validate(r300, FALSE, NULL); r300_emit_dirty_state(r300); BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(count - 1); + OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); @@ -202,7 +203,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Emit vertices. */ for (v = 0; v < count; v++) { for (i = 0; i < vertex_element_count; i++) { - velem = &r300->vertex_element[i]; + velem = &r300->velems->velem[i]; vbi = velem->vertex_buffer_index; elem_offset = offset[i] + stride[vbi] * (v + start); @@ -215,7 +216,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Unmap buffers. */ for (i = 0; i < vertex_element_count; i++) { - vbi = r300->vertex_element[i].vertex_buffer_index; + vbi = r300->velems->velem[i].vertex_buffer_index; if (map[vbi]) { vbuf = &r300->vertex_buffer[vbi]; @@ -238,15 +239,16 @@ static void r300_emit_draw_arrays(struct r300_context *r300, if (alt_num_verts) { assert(count < (1 << 24)); - BEGIN_CS(10); + BEGIN_CS(9); OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } else { - BEGIN_CS(8); + BEGIN_CS(7); } OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(count - 1); + OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300_translate_primitive(mode) | @@ -278,18 +280,19 @@ static void r300_emit_draw_elements(struct r300_context *r300, DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); - maxIndex = MIN2(maxIndex, ((1 << 24) - 1)); + maxIndex = MIN3(maxIndex, r300->vertex_buffer_max_index, (1 << 24) - 1); if (alt_num_verts) { - BEGIN_CS(16); + BEGIN_CS(15); OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } else { - BEGIN_CS(14); + BEGIN_CS(13); } OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, minIndex); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(maxIndex); + OUT_CS(minIndex); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); if (indexSize == 4) { count_dwords = count; @@ -450,7 +453,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, /* Make sure there are at least 128 spare dwords in the command buffer. * (most of it being consumed by emit_aos) */ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); - r300_emit_buffer_validate(r300, TRUE, 0); + r300_emit_buffer_validate(r300, TRUE, NULL); r300_emit_dirty_state(r300); if (alt_num_verts || count <= 65535) { @@ -468,7 +471,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, /* Again, we emit both AOS and draw_arrays so there should be * at least 128 spare dwords. */ if (count && r300_reserve_cs_space(r300, 128)) { - r300_emit_buffer_validate(r300, TRUE, 0); + r300_emit_buffer_validate(r300, TRUE, NULL); r300_emit_dirty_state(r300); } } while (count); @@ -688,6 +691,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render, CS_LOCALS(r300); r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2); + r300_emit_buffer_validate(r300, FALSE, NULL); r300_emit_dirty_state(r300); DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); @@ -711,6 +715,7 @@ static void r300_render_draw(struct vbuf_render* render, CS_LOCALS(r300); r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); + r300_emit_buffer_validate(r300, FALSE, NULL); r300_emit_dirty_state(r300); BEGIN_CS(dwords); diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index d397a8eb2b4..64d1909a382 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,13 +21,11 @@ * 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_format.h" #include "util/u_memory.h" #include "util/u_simple_screen.h" #include "r300_context.h" -#include "r300_screen.h" #include "r300_texture.h" #include "radeon_winsys.h" @@ -231,14 +230,16 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, /* Check colorbuffer format support. */ if ((usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) && + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) && /* 2101010 cannot be rendered to on non-r5xx. */ (is_r500 || !is_color2101010) && r300_is_colorbuffer_format_supported(format)) { retval |= usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED); } /* Check depth-stencil format support. */ @@ -250,70 +251,6 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, return retval == usage; } -static struct pipe_transfer* -r300_get_tex_transfer(struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, unsigned x, unsigned y, - unsigned w, unsigned h) -{ - struct r300_texture *tex = (struct r300_texture *)texture; - struct r300_transfer *trans; - struct r300_screen *rscreen = r300_screen(screen); - unsigned offset; - - offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */ - - trans = CALLOC_STRUCT(r300_transfer); - if (trans) { - pipe_texture_reference(&trans->transfer.texture, texture); - trans->transfer.x = x; - trans->transfer.y = y; - trans->transfer.width = w; - trans->transfer.height = h; - trans->transfer.stride = r300_texture_get_stride(rscreen, tex, level); - trans->transfer.usage = usage; - trans->transfer.zslice = zslice; - trans->transfer.face = face; - - trans->offset = offset; - } - return &trans->transfer; -} - -static void -r300_tex_transfer_destroy(struct pipe_transfer *trans) -{ - pipe_texture_reference(&trans->texture, NULL); - FREE(trans); -} - -static void* r300_transfer_map(struct pipe_screen* screen, - struct pipe_transfer* transfer) -{ - struct r300_texture* tex = (struct r300_texture*)transfer->texture; - char* map; - enum pipe_format format = tex->tex.format; - - map = pipe_buffer_map(screen, tex->buffer, - pipe_transfer_buffer_flags(transfer)); - - if (!map) { - return NULL; - } - - return map + r300_transfer(transfer)->offset + - transfer->y / util_format_get_blockheight(format) * transfer->stride + - transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); -} - -static void r300_transfer_unmap(struct pipe_screen* screen, - struct pipe_transfer* transfer) -{ - struct r300_texture* tex = (struct r300_texture*)transfer->texture; - pipe_buffer_unmap(screen, tex->buffer); -} - static void r300_destroy_screen(struct pipe_screen* pscreen) { struct r300_screen* r300screen = r300_screen(pscreen); @@ -350,13 +287,10 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) r300screen->screen.get_paramf = r300_get_paramf; r300screen->screen.is_format_supported = r300_is_format_supported; r300screen->screen.context_create = r300_create_context; - r300screen->screen.get_tex_transfer = r300_get_tex_transfer; - r300screen->screen.tex_transfer_destroy = r300_tex_transfer_destroy; - r300screen->screen.transfer_map = r300_transfer_map; - r300screen->screen.transfer_unmap = r300_transfer_unmap; r300_init_screen_texture_functions(&r300screen->screen); u_simple_screen_init(&r300screen->screen); return &r300screen->screen; } + diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 502fbfa5a24..484bde6a6be 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,6 +28,8 @@ #include "r300_chipset.h" +#define R300_TEXTURE_USAGE_TRANSFER PIPE_TEXTURE_USAGE_CUSTOM + struct radeon_winsys; struct r300_screen { @@ -35,6 +38,10 @@ struct r300_screen { struct radeon_winsys* radeon_winsys; + /* XXX This hack will be removed once texture transfers become part of + * pipe_context. */ + struct pipe_context* ctx; + /* Chipset capabilities */ struct r300_capabilities* caps; @@ -42,25 +49,14 @@ struct r300_screen { unsigned debug; }; -struct r300_transfer { - /* Parent class */ - struct pipe_transfer transfer; - - /* Offset from start of buffer. */ - unsigned offset; -}; /* Convenience cast wrapper. */ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { return (struct r300_screen*)screen; } -/* Convenience cast wrapper. */ -static INLINE struct r300_transfer* -r300_transfer(struct pipe_transfer* transfer) -{ - return (struct r300_transfer*)transfer; -} +/* Creates a new r300 screen. */ +struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); /* Debug functionality. */ diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 1f6f99d3e52..ced6c810ec5 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -571,6 +571,7 @@ static void { struct r300_context* r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(pipe->screen); + struct pipe_framebuffer_state *old_state = r300->fb_state.state; unsigned max_width, max_height; uint32_t zbuffer_bpp = 0; @@ -595,23 +596,30 @@ static void return; } - if (r300->draw) { draw_flush(r300->draw); } - memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); + r300->fb_state.dirty = TRUE; - r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 8; + /* If nr_cbufs is changed from zero to non-zero or vice versa... */ + if (!!old_state->nr_cbufs != !!state->nr_cbufs) { + r300->blend_state.dirty = TRUE; + } + /* If zsbuf is set from NULL to non-NULL or vice versa.. */ + if (!!old_state->zsbuf != !!state->zsbuf) { + r300->dsa_state.dirty = TRUE; + } + if (!r300->scissor_enabled) { + r300->scissor_state.dirty = TRUE; + } r300_fb_update_tiling_flags(r300, r300->fb_state.state, state); - /* XXX wait what */ - r300->blend_state.dirty = TRUE; - r300->dsa_state.dirty = TRUE; - r300->fb_state.dirty = TRUE; - r300->scissor_state.dirty = TRUE; + memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); + + r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + + (state->zsbuf ? 10 : 0) + 8; /* Polygon offset depends on the zbuffer bit depth. */ if (state->zsbuf && r300->polygon_offset_enabled) { @@ -716,8 +724,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->vap_control_status = R300_VC_32BIT_SWAP; #endif - /* If bypassing TCL, or if no TCL engine is present, turn off the HW TCL. - * Else, enable HW TCL and force Draw's TCL off. */ + /* If no TCL engine is present, turn off the HW TCL. */ if (!r300screen->caps->has_tcl) { rs->vap_control_status |= R300_VAP_TCL_BYPASS; } @@ -807,6 +814,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; + boolean scissor_was_enabled = r300->scissor_enabled; if (r300->draw) { draw_flush(r300->draw); @@ -815,20 +823,17 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; + r300->scissor_enabled = rs->rs.scissor; } else { r300->polygon_offset_enabled = FALSE; + r300->scissor_enabled = FALSE; } UPDATE_STATE(state, r300->rs_state); r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); - /* XXX Why is this still needed, dammit!? */ - r300->scissor_state.dirty = TRUE; - r300->viewport_state.dirty = TRUE; - - /* XXX Clean these up when we move to atom emits */ - if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { - r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + if (scissor_was_enabled != r300->scissor_enabled) { + r300->scissor_state.dirty = TRUE; } } @@ -973,7 +978,9 @@ static void r300_set_scissor_state(struct pipe_context* pipe, memcpy(r300->scissor_state.state, state, sizeof(struct pipe_scissor_state)); - r300->scissor_state.dirty = TRUE; + if (r300->scissor_enabled) { + r300->scissor_state.dirty = TRUE; + } } static void r300_set_viewport_state(struct pipe_context* pipe, @@ -1024,7 +1031,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - unsigned i, max_index = ~0; + unsigned i, max_index = (1 << 24) - 1; memcpy(r300->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); @@ -1039,19 +1046,17 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, if (r300->draw) { draw_flush(r300->draw); draw_set_vertex_buffers(r300->draw, count, buffers); - } else { - r300->vertex_stream_state.dirty = TRUE; } } static boolean r300_validate_aos(struct r300_context *r300) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_vertex_element *velem = r300->velems->velem; int i; /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->vertex_element_count; i++) { + for (i = 0; i < r300->velems->count; i++) { if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || util_format_get_blocksize(velem[i].src_format) % 4 != 0) { return FALSE; @@ -1060,20 +1065,209 @@ static boolean r300_validate_aos(struct r300_context *r300) return TRUE; } -static void r300_set_vertex_elements(struct pipe_context* pipe, - unsigned count, - const struct pipe_vertex_element* elements) +static void r300_draw_emit_attrib(struct r300_context* r300, + enum attrib_emit emit, + enum interp_mode interp, + int index) { - struct r300_context* r300 = r300_context(pipe); + struct r300_vertex_shader* vs = r300->vs_state.state; + struct tgsi_shader_info* info = &vs->info; + int output; + + output = draw_find_shader_output(r300->draw, + info->output_semantic_name[index], + info->output_semantic_index[index]); + draw_emit_vertex_attr(&r300->vertex_info, emit, interp, output); +} + +static void r300_draw_emit_all_attribs(struct r300_context* r300) +{ + struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_shader_semantics* vs_outputs = &vs->outputs; + int i, gen_count; + + /* Position. */ + if (vs_outputs->pos != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->pos); + } else { + assert(0); + } + + /* Point size. */ + if (vs_outputs->psize != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, INTERP_POS, + vs_outputs->psize); + } + + /* Colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (vs_outputs->color[i] != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_LINEAR, + vs_outputs->color[i]); + } + } + + /* XXX Back-face colors. */ - memcpy(r300->vertex_element, - elements, - sizeof(struct pipe_vertex_element) * count); - r300->vertex_element_count = count; + /* Texture coordinates. */ + gen_count = 0; + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (vs_outputs->generic[i] != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->generic[i]); + gen_count++; + } + } + + /* Fog coordinates. */ + if (vs_outputs->fog != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->fog); + gen_count++; + } + + /* XXX magic */ + assert(gen_count <= 8); +} + +/* Update the PSC tables. */ +static void r300_vertex_psc(struct r300_vertex_element_state *velems) +{ + struct r300_vertex_stream_state *vstream = &velems->vertex_stream; + uint16_t type, swizzle; + enum pipe_format format; + unsigned i; + + assert(velems->count <= 16); + + /* Vertex shaders have no semantics on their inputs, + * so PSC should just route stuff based on the vertex elements, + * and not on attrib information. */ + for (i = 0; i < velems->count; i++) { + format = velems->velem[i].src_format; + + type = r300_translate_vertex_data_type(format) | + (i << R300_DST_VEC_LOC_SHIFT); + swizzle = r300_translate_vertex_data_swizzle(format); + + if (i & 1) { + vstream->vap_prog_stream_cntl[i >> 1] |= type << 16; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + } else { + vstream->vap_prog_stream_cntl[i >> 1] |= type; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; + } + } + + /* Set the last vector in the PSC. */ + if (i) { + i -= 1; + } + vstream->vap_prog_stream_cntl[i >> 1] |= + (R300_LAST_VEC << (i & 1 ? 16 : 0)); + + vstream->count = (i >> 1) + 1; +} + +/* Update the PSC tables for SW TCL, using Draw. */ +static void r300_swtcl_vertex_psc(struct r300_context *r300, + struct r300_vertex_element_state *velems) +{ + struct r300_vertex_stream_state *vstream = &velems->vertex_stream; + struct r300_vertex_shader* vs = r300->vs_state.state; + struct vertex_info* vinfo = &r300->vertex_info; + uint16_t type, swizzle; + enum pipe_format format; + unsigned i, attrib_count; + int* vs_output_tab = vs->stream_loc_notcl; + + /* For each Draw attribute, route it to the fragment shader according + * to the vs_output_tab. */ + attrib_count = vinfo->num_attribs; + DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); + for (i = 0; i < attrib_count; i++) { + DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," + " vs_output_tab %d\n", vinfo->attrib[i].src_index, + vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, + vs_output_tab[i]); + } + + for (i = 0; i < attrib_count; i++) { + /* Make sure we have a proper destination for our attribute. */ + assert(vs_output_tab[i] != -1); + + format = draw_translate_vinfo_format(vinfo->attrib[i].emit); + + /* Obtain the type of data in this attribute. */ + type = r300_translate_vertex_data_type(format) | + vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT; + + /* Obtain the swizzle for this attribute. Note that the default + * swizzle in the hardware is not XYZW! */ + swizzle = r300_translate_vertex_data_swizzle(format); + + /* Add the attribute to the PSC table. */ + if (i & 1) { + vstream->vap_prog_stream_cntl[i >> 1] |= type << 16; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + } else { + vstream->vap_prog_stream_cntl[i >> 1] |= type; + vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; + } + } + + /* Set the last vector in the PSC. */ + if (i) { + i -= 1; + } + vstream->vap_prog_stream_cntl[i >> 1] |= + (R300_LAST_VEC << (i & 1 ? 16 : 0)); + + vstream->count = (i >> 1) + 1; +} + +static void* r300_create_vertex_elements_state(struct pipe_context* pipe, + unsigned count, + const struct pipe_vertex_element* attribs) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(pipe->screen); + struct r300_vertex_element_state *velems; + + assert(count <= PIPE_MAX_ATTRIBS); + velems = CALLOC_STRUCT(r300_vertex_element_state); + if (velems != NULL) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); + + if (r300screen->caps->has_tcl) { + r300_vertex_psc(velems); + } else { + memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); + r300_draw_emit_all_attribs(r300); + draw_compute_vertex_size(&r300->vertex_info); + r300_swtcl_vertex_psc(r300, velems); + } + } + return velems; +} + +static void r300_bind_vertex_elements_state(struct pipe_context *pipe, + void *state) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_vertex_element_state *velems = state; + + if (velems == NULL) { + return; + } + + r300->velems = velems; if (r300->draw) { draw_flush(r300->draw); - draw_set_vertex_elements(r300->draw, count, elements); + draw_set_vertex_elements(r300->draw, velems->count, velems->velem); } if (!r300_validate_aos(r300)) { @@ -1081,6 +1275,14 @@ static void r300_set_vertex_elements(struct pipe_context* pipe, assert(0); abort(); } + + UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); + r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; +} + +static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) +{ + FREE(state); } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -1088,68 +1290,71 @@ static void* r300_create_vs_state(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); - if (r300_screen(pipe->screen)->caps->has_tcl) { - struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); - /* Copy state directly into shader. */ - vs->state = *shader; - vs->state.tokens = tgsi_dup_tokens(shader->tokens); - - tgsi_scan_shader(shader->tokens, &vs->info); + struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); + r300_vertex_shader_common_init(vs, shader); - return (void*)vs; + if (r300_screen(pipe->screen)->caps->has_tcl) { + r300_translate_vertex_shader(r300, vs); } else { - return draw_create_vertex_shader(r300->draw, shader); + vs->draw_vs = draw_create_vertex_shader(r300->draw, shader); } + + return vs; } static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); + struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - if (r300_screen(pipe->screen)->caps->has_tcl) { - struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; + if (vs == NULL) { + r300->vs_state.state = NULL; + return; + } + if (vs == r300->vs_state.state) { + return; + } + r300->vs_state.state = vs; - if (vs == NULL) { - r300->vs_state.state = NULL; - return; - } else if (!vs->translated) { - r300_translate_vertex_shader(r300, vs); - } + // VS output mapping for HWTCL or stream mapping for SWTCL to the RS block + if (r300->fs) { + r300_vertex_shader_setup_wpos(r300); + } + memcpy(r300->vap_output_state.state, &vs->vap_out, + sizeof(struct r300_vap_output_state)); + r300->vap_output_state.dirty = TRUE; - UPDATE_STATE(shader, r300->vs_state); + /* The majority of the RS block bits is dependent on the vertex shader. */ + r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ + + if (r300_screen(pipe->screen)->caps->has_tcl) { + r300->vs_state.dirty = TRUE; r300->vs_state.size = vs->code.length + 9; - r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ - r300->vap_output_state.dirty = TRUE; - r300->vertex_stream_state.dirty = TRUE; /* XXX needed for TCL bypass */ r300->pvs_flush.dirty = TRUE; - if (r300->fs) { - r300_vertex_shader_setup_wpos(r300); - } - r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, - (struct draw_vertex_shader*)shader); + (struct draw_vertex_shader*)vs->draw_vs); } } static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); + struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; if (r300_screen(pipe->screen)->caps->has_tcl) { - struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - rc_constants_destroy(&vs->code.constants); - FREE((void*)vs->state.tokens); - FREE(shader); } else { draw_delete_vertex_shader(r300->draw, - (struct draw_vertex_shader*)shader); + (struct draw_vertex_shader*)vs->draw_vs); } + + FREE((void*)vs->state.tokens); + FREE(shader); } static void r300_set_constant_buffer(struct pipe_context *pipe, @@ -1201,8 +1406,10 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, pipe_buffer_unmap(pipe->screen, buf); if (shader == PIPE_SHADER_VERTEX) { - r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; - r300->pvs_flush.dirty = TRUE; + if (r300screen->caps->has_tcl) { + r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; + r300->pvs_flush.dirty = TRUE; + } } else if (shader == PIPE_SHADER_FRAGMENT) r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -1250,7 +1457,10 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.set_viewport_state = r300_set_viewport_state; r300->context.set_vertex_buffers = r300_set_vertex_buffers; - r300->context.set_vertex_elements = r300_set_vertex_elements; + + r300->context.create_vertex_elements_state = r300_create_vertex_elements_state; + r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state; + r300->context.delete_vertex_elements_state = r300_delete_vertex_elements_state; r300->context.create_vs_state = r300_create_vs_state; r300->context.bind_vs_state = r300_bind_vs_state; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 9c8e907fdf7..6b9f61acd7b 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -37,187 +37,6 @@ /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ -static void r300_draw_emit_attrib(struct r300_context* r300, - enum attrib_emit emit, - enum interp_mode interp, - int index) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct tgsi_shader_info* info = &vs->info; - int output; - - output = draw_find_shader_output(r300->draw, - info->output_semantic_name[index], - info->output_semantic_index[index]); - draw_emit_vertex_attr(&r300->vertex_info, emit, interp, output); -} - -static void r300_draw_emit_all_attribs(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_shader_semantics* vs_outputs = &vs->outputs; - int i, gen_count; - - /* Position. */ - if (vs_outputs->pos != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->pos); - } else { - assert(0); - } - - /* Point size. */ - if (vs_outputs->psize != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, INTERP_POS, - vs_outputs->psize); - } - - /* Colors. */ - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_LINEAR, - vs_outputs->color[i]); - } - } - - /* XXX Back-face colors. */ - - /* Texture coordinates. */ - gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->generic[i]); - gen_count++; - } - } - - /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->fog); - gen_count++; - } - - /* XXX magic */ - assert(gen_count <= 8); -} - -/* Update the PSC tables. */ -/* XXX move this function into r300_state.c after TCL-bypass gets removed - * XXX because this one is dependent only on vertex elements. */ -static void r300_vertex_psc(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_vertex_stream_state *vformat = - (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; - uint16_t type, swizzle; - enum pipe_format format; - unsigned i; - int identity[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - int* stream_tab; - - memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); - - stream_tab = identity; - - /* Vertex shaders have no semantics on their inputs, - * so PSC should just route stuff based on the vertex elements, - * and not on attrib information. */ - DBG(r300, DBG_DRAW, "r300: vs expects %d attribs, routing %d elements" - " in psc\n", - vs->info.num_inputs, - r300->vertex_element_count); - - for (i = 0; i < r300->vertex_element_count; i++) { - format = r300->vertex_element[i].src_format; - - type = r300_translate_vertex_data_type(format) | - (stream_tab[i] << R300_DST_VEC_LOC_SHIFT); - swizzle = r300_translate_vertex_data_swizzle(format); - - if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; - } else { - vformat->vap_prog_stream_cntl[i >> 1] |= type; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; - } - } - - assert(i <= 15); - - /* Set the last vector in the PSC. */ - if (i) { - i -= 1; - } - vformat->vap_prog_stream_cntl[i >> 1] |= - (R300_LAST_VEC << (i & 1 ? 16 : 0)); - - vformat->count = (i >> 1) + 1; - r300->vertex_stream_state.size = (1 + vformat->count) * 2; -} - -/* Update the PSC tables for SW TCL, using Draw. */ -static void r300_swtcl_vertex_psc(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_vertex_stream_state *vformat = - (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; - struct vertex_info* vinfo = &r300->vertex_info; - uint16_t type, swizzle; - enum pipe_format format; - unsigned i, attrib_count; - int* vs_output_tab = vs->stream_loc_notcl; - - memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); - - /* For each Draw attribute, route it to the fragment shader according - * to the vs_output_tab. */ - attrib_count = vinfo->num_attribs; - DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); - for (i = 0; i < attrib_count; i++) { - DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," - " vs_output_tab %d\n", vinfo->attrib[i].src_index, - vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, - vs_output_tab[i]); - } - - for (i = 0; i < attrib_count; i++) { - /* Make sure we have a proper destination for our attribute. */ - assert(vs_output_tab[i] != -1); - - format = draw_translate_vinfo_format(vinfo->attrib[i].emit); - - /* Obtain the type of data in this attribute. */ - type = r300_translate_vertex_data_type(format) | - vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT; - - /* Obtain the swizzle for this attribute. Note that the default - * swizzle in the hardware is not XYZW! */ - swizzle = r300_translate_vertex_data_swizzle(format); - - /* Add the attribute to the PSC table. */ - if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; - } else { - vformat->vap_prog_stream_cntl[i >> 1] |= type; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; - } - } - - /* Set the last vector in the PSC. */ - if (i) { - i -= 1; - } - vformat->vap_prog_stream_cntl[i >> 1] |= - (R300_LAST_VEC << (i & 1 ? 16 : 0)); - - vformat->count = (i >> 1) + 1; - r300->vertex_stream_state.size = (1 + vformat->count) * 2; -} - static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr, boolean swizzle_0001) { @@ -432,23 +251,8 @@ static void r300_update_rs_block(struct r300_context* r300, static void r300_update_derived_shader_state(struct r300_context* r300) { struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct r300_vap_output_state *vap_out = - (struct r300_vap_output_state*)r300->vap_output_state.state; - - /* XXX Mmm, delicious hax */ - memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); - memcpy(vap_out, vs->hwfmt, sizeof(uint)*4); r300_update_rs_block(r300, &vs->outputs, &r300->fs->inputs); - - if (r300screen->caps->has_tcl) { - r300_vertex_psc(r300); - } else { - r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info); - r300_swtcl_vertex_psc(r300); - } } static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) @@ -581,9 +385,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) void r300_update_derived_state(struct r300_context* r300) { - if (r300->rs_block_state.dirty || - r300->vertex_stream_state.dirty || /* XXX put updating this state out of this file */ - r300->rs_state.dirty) { /* XXX and remove this one (tcl_bypass dependency) */ + if (r300->rs_block_state.dirty) { r300_update_derived_shader_state(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 2f3a56e1fbc..a32924ed0a3 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -348,39 +348,12 @@ static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) return 0; } -/* Utility function to count the number of components in RGBAZS formats. - * XXX should go to util or p_format.h */ -static INLINE unsigned pf_component_count(enum pipe_format format) { - unsigned count = 0; - - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 1)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 2)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 3)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { - count++; - } - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { - count++; - } - - return count; -} - /* Translate pipe_formats into PSC vertex types. */ static INLINE uint16_t r300_translate_vertex_data_type(enum pipe_format format) { uint32_t result = 0; const struct util_format_description *desc; - unsigned components = pf_component_count(format); + unsigned components = util_format_get_nr_components(format); desc = util_format_description(format); @@ -453,7 +426,6 @@ r300_translate_vertex_data_type(enum pipe_format format) { static INLINE uint16_t r300_translate_vertex_data_swizzle(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); - unsigned swizzle[4], i; assert(format); @@ -463,25 +435,10 @@ r300_translate_vertex_data_swizzle(enum pipe_format format) { return 0; } - /* Swizzles for 8bits formats are in the reversed order, not sure why. */ - if (desc->channel[0].size == 8) { - for (i = 0; i < 4; i++) { - if (desc->swizzle[i] <= 3) { - swizzle[i] = 3 - desc->swizzle[i]; - } else { - swizzle[i] = desc->swizzle[i]; - } - } - } else { - for (i = 0; i < 4; i++) { - swizzle[i] = desc->swizzle[i]; - } - } - - return ((swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | - (swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | - (swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | - (swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | + return ((desc->swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | + (desc->swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | + (desc->swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | + (desc->swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | (0xf << R300_WRITE_ENA_SHIFT)); } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index c0144f64b4a..04124afd4dc 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -617,18 +617,23 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex, /* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_texture *tex, unsigned level, - boolean rv350_mode) + boolean rv350_mode, + int dim) { - unsigned tile_width, width; + unsigned tile, texdim; - tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, TRUE); - width = u_minify(tex->tex.width0, level); + tile = r300_texture_get_tile_size(tex, dim, TRUE); + if (dim == TILE_WIDTH) { + texdim = u_minify(tex->tex.width0, level); + } else { + texdim = u_minify(tex->tex.height0, level); + } /* See TX_FILTER1_n.MACRO_SWITCH. */ if (rv350_mode) { - return width >= tile_width; + return texdim >= tile; } else { - return width > tile_width; + return texdim > tile; } } @@ -692,9 +697,10 @@ static void r300_setup_miptree(struct r300_screen* screen, for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ - tex->mip_macrotile[i] = (tex->macrotile == R300_BUFFER_TILED && - r300_texture_macro_switch(tex, i, rv350_mode)) ? - R300_BUFFER_TILED : R300_BUFFER_LINEAR; + tex->mip_macrotile[i] = + (tex->macrotile == R300_BUFFER_TILED && + r300_texture_macro_switch(tex, i, rv350_mode, TILE_WIDTH)) ? + R300_BUFFER_TILED : R300_BUFFER_LINEAR; stride = r300_texture_get_stride(screen, tex, i); nblocksy = r300_texture_get_nblocksy(tex, i); @@ -724,10 +730,46 @@ static void r300_setup_flags(struct r300_texture* tex) !util_is_power_of_two(tex->tex.height0); } +static void r300_setup_tiling(struct pipe_screen *screen, + struct r300_texture *tex) +{ + enum pipe_format format = tex->tex.format; + boolean rv350_mode = r300_screen(screen)->caps->family >= CHIP_FAMILY_RV350; + + if (util_format_is_compressed(format)) { + return; + } + + if (tex->tex.width0 == 1 || + tex->tex.height0 == 1) { + return; + } + + /* Set microtiling. */ + switch (util_format_get_blocksize(format)) { + case 1: + case 4: + tex->microtile = R300_BUFFER_TILED; + break; + + /* XXX Square-tiling doesn't work with kernel older than 2.6.34, + * XXX need to check the DRM version */ + /*case 2: + case 8: + tex->microtile = R300_BUFFER_SQUARETILED; + break;*/ + } + + /* Set macrotiling. */ + if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) && + r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) { + tex->macrotile = R300_BUFFER_TILED; + } +} + /* Create a new texture. */ -static struct pipe_texture* - r300_texture_create(struct pipe_screen* screen, - const struct pipe_texture* template) +static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, + const struct pipe_texture* template) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); struct r300_screen* rscreen = r300_screen(screen); @@ -742,6 +784,9 @@ static struct pipe_texture* tex->tex.screen = screen; r300_setup_flags(tex); + if (!(template->tex_usage & R300_TEXTURE_USAGE_TRANSFER)) { + r300_setup_tiling(screen, tex); + } r300_setup_miptree(rscreen, tex); r300_setup_texture_state(rscreen, tex); @@ -806,14 +851,17 @@ static void r300_tex_surface_destroy(struct pipe_surface* s) FREE(s); } + static struct pipe_texture* - r300_texture_blanket(struct pipe_screen* screen, - const struct pipe_texture* base, - const unsigned* stride, - struct pipe_buffer* buffer) + r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_texture* base, + struct winsys_handle *whandle) { - struct r300_texture* tex; + struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; struct r300_screen* rscreen = r300_screen(screen); + struct pipe_buffer *buffer; + struct r300_texture* tex; + unsigned stride; /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || @@ -822,6 +870,11 @@ static struct pipe_texture* return NULL; } + buffer = winsys->buffer_from_handle(winsys, screen, whandle, &stride); + if (!buffer) { + return NULL; + } + tex = CALLOC_STRUCT(r300_texture); if (!tex) { return NULL; @@ -831,17 +884,38 @@ static struct pipe_texture* pipe_reference_init(&tex->tex.reference, 1); tex->tex.screen = screen; - tex->stride_override = *stride; - tex->pitch[0] = *stride / util_format_get_blocksize(base->format); + tex->stride_override = stride; + tex->pitch[0] = stride / util_format_get_blocksize(base->format); r300_setup_flags(tex); r300_setup_texture_state(rscreen, tex); - pipe_buffer_reference(&tex->buffer, buffer); + /* one ref already taken */ + tex->buffer = buffer; return (struct pipe_texture*)tex; } +static boolean + r300_texture_get_handle(struct pipe_screen* screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; + struct r300_texture* tex = (struct r300_texture*)texture; + unsigned stride; + + if (!tex) { + return FALSE; + } + + stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + + winsys->buffer_get_handle(winsys, tex->buffer, stride, whandle); + + return TRUE; +} + static struct pipe_video_surface * r300_video_surface_create(struct pipe_screen *screen, enum pipe_video_chroma_format chroma_format, @@ -893,30 +967,13 @@ static void r300_video_surface_destroy(struct pipe_video_surface *vsfc) void r300_init_screen_texture_functions(struct pipe_screen* screen) { screen->texture_create = r300_texture_create; + screen->texture_from_handle = r300_texture_from_handle; + screen->texture_get_handle = r300_texture_get_handle; screen->texture_destroy = r300_texture_destroy; screen->get_tex_surface = r300_get_tex_surface; screen->tex_surface_destroy = r300_tex_surface_destroy; - screen->texture_blanket = r300_texture_blanket; screen->video_surface_create = r300_video_surface_create; screen->video_surface_destroy= r300_video_surface_destroy; } -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct pipe_buffer** buffer, - unsigned* stride) -{ - struct r300_texture* tex = (struct r300_texture*)texture; - if (!tex) { - return FALSE; - } - - pipe_buffer_reference(buffer, tex->buffer); - - if (stride) { - *stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - } - - return TRUE; -} diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 46a5fb6188b..138b62784e6 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -60,13 +60,11 @@ r300_video_surface(struct pipe_video_surface *pvs) return (struct r300_video_surface *)pvs; } -#ifndef R300_WINSYS_H - +/* Used internally for texture_is_referenced() + */ boolean r300_get_texture_buffer(struct pipe_screen* screen, struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); -#endif /* R300_WINSYS_H */ - #endif /* R300_TEXTURE_H */ diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c new file mode 100644 index 00000000000..495e3dee767 --- /dev/null +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -0,0 +1,276 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> + * + * 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 + * on 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 + * THE AUTHOR(S) AND/OR THEIR 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 "r300_context.h" +#include "r300_transfer.h" +#include "r300_texture.h" +#include "r300_screen.h" + +#include "util/u_memory.h" +#include "util/u_format.h" + +struct r300_transfer { + /* Parent class */ + struct pipe_transfer transfer; + + /* Pipe context. */ + struct pipe_context *ctx; + + /* Parameters of get_tex_transfer. */ + unsigned x, y, level, zslice, face; + + /* Offset from start of buffer. */ + unsigned offset; + + /* Detiled texture. */ + struct r300_texture *detiled_texture; + + /* Transfer and format flags. */ + unsigned buffer_usage, render_target_usage; +}; + +/* Convenience cast wrapper. */ +static INLINE struct r300_transfer* +r300_transfer(struct pipe_transfer* transfer) +{ + return (struct r300_transfer*)transfer; +} + +/* Copy from a tiled texture to a detiled one. */ +static void r300_copy_from_tiled_texture(struct pipe_context *ctx, + struct r300_transfer *r300transfer) +{ + struct pipe_screen *screen = ctx->screen; + struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; + struct pipe_texture *tex = transfer->texture; + struct pipe_surface *src, *dst; + + src = screen->get_tex_surface(screen, tex, r300transfer->face, + r300transfer->level, r300transfer->zslice, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_PIXEL); + + dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE | + PIPE_BUFFER_USAGE_PIXEL | + r300transfer->buffer_usage); + + ctx->surface_copy(ctx, dst, 0, 0, src, r300transfer->x, r300transfer->y, + transfer->width, transfer->height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +/* Copy a detiled texture to a tiled one. */ +static void r300_copy_into_tiled_texture(struct pipe_context *ctx, + struct r300_transfer *r300transfer) +{ + struct pipe_screen *screen = ctx->screen; + struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; + struct pipe_texture *tex = transfer->texture; + struct pipe_surface *src, *dst; + + src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_PIXEL); + + dst = screen->get_tex_surface(screen, tex, r300transfer->face, + r300transfer->level, r300transfer->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE | + PIPE_BUFFER_USAGE_PIXEL); + + /* XXX this flush prevents the following DRM error from occuring: + * [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation ! + * Reproducible with perf/copytex. */ + ctx->flush(ctx, 0, NULL); + + ctx->surface_copy(ctx, dst, r300transfer->x, r300transfer->y, src, 0, 0, + transfer->width, transfer->height); + + /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */ + ctx->flush(ctx, 0, NULL); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +static struct pipe_transfer* +r300_get_tex_transfer(struct pipe_context *ctx, + struct pipe_texture *texture, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, unsigned x, unsigned y, + unsigned w, unsigned h) +{ + struct r300_texture *tex = (struct r300_texture *)texture; + struct r300_screen *r300screen = r300_screen(ctx->screen); + struct r300_transfer *trans; + struct pipe_texture template; + + trans = CALLOC_STRUCT(r300_transfer); + if (trans) { + /* Initialize the transfer object. */ + pipe_texture_reference(&trans->transfer.texture, texture); + trans->transfer.usage = usage; + trans->transfer.width = w; + trans->transfer.height = h; + trans->ctx = ctx; + trans->x = x; + trans->y = y; + trans->level = level; + trans->zslice = zslice; + trans->face = face; + + /* If the texture is tiled, we must create a temporary detiled texture + * for this transfer. */ + if (tex->microtile || tex->macrotile) { + trans->buffer_usage = pipe_transfer_buffer_flags(&trans->transfer); + trans->render_target_usage = + util_format_is_depth_or_stencil(texture->format) ? + PIPE_TEXTURE_USAGE_DEPTH_STENCIL : + PIPE_TEXTURE_USAGE_RENDER_TARGET; + + template.target = PIPE_TEXTURE_2D; + template.format = texture->format; + template.width0 = w; + template.height0 = h; + template.depth0 = 0; + template.last_level = 0; + template.nr_samples = 0; + template.tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + R300_TEXTURE_USAGE_TRANSFER; + + /* For texture reading, the temporary (detiled) texture is used as + * a render target when blitting from a tiled texture. */ + if (usage & PIPE_TRANSFER_READ) { + template.tex_usage |= trans->render_target_usage; + } + /* For texture writing, the temporary texture is used as a sampler + * when blitting into a tiled texture. */ + if (usage & PIPE_TRANSFER_WRITE) { + template.tex_usage |= PIPE_TEXTURE_USAGE_SAMPLER; + } + + /* Create the temporary texture. */ + trans->detiled_texture = (struct r300_texture*) + ctx->screen->texture_create(ctx->screen, + &template); + + assert(!trans->detiled_texture->microtile && + !trans->detiled_texture->macrotile); + + /* Set the stride. + * Parameters x, y, level, zslice, and face remain zero. */ + trans->transfer.stride = + r300_texture_get_stride(r300screen, trans->detiled_texture, 0); + + if (usage & PIPE_TRANSFER_READ) { + /* We cannot map a tiled texture directly because the data is + * in a different order, therefore we do detiling using a blit. */ + r300_copy_from_tiled_texture(ctx, trans); + } + } else { + trans->transfer.x = x; + trans->transfer.y = y; + trans->transfer.stride = + r300_texture_get_stride(r300screen, tex, level); + trans->transfer.level = level; + trans->transfer.zslice = zslice; + trans->transfer.face = face; + trans->offset = r300_texture_get_offset(tex, level, zslice, face); + } + } + return &trans->transfer; +} + +static void r300_tex_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *trans) +{ + struct r300_transfer *r300transfer = r300_transfer(trans); + + if (r300transfer->detiled_texture) { + if (trans->usage & PIPE_TRANSFER_WRITE) { + r300_copy_into_tiled_texture(r300transfer->ctx, r300transfer); + } + + pipe_texture_reference( + (struct pipe_texture**)&r300transfer->detiled_texture, NULL); + } + pipe_texture_reference(&trans->texture, NULL); + FREE(trans); +} + +static void* r300_transfer_map(struct pipe_context *ctx, + struct pipe_transfer *transfer) +{ + struct r300_transfer *r300transfer = r300_transfer(transfer); + struct r300_texture *tex = (struct r300_texture*)transfer->texture; + char *map; + enum pipe_format format = tex->tex.format; + + if (r300transfer->detiled_texture) { + /* The detiled texture is of the same size as the region being mapped + * (no offset needed). */ + return pipe_buffer_map(ctx->screen, + r300transfer->detiled_texture->buffer, + pipe_transfer_buffer_flags(transfer)); + } else { + /* Tiling is disabled. */ + map = pipe_buffer_map(ctx->screen, tex->buffer, + pipe_transfer_buffer_flags(transfer)); + + if (!map) { + return NULL; + } + + return map + r300_transfer(transfer)->offset + + transfer->y / util_format_get_blockheight(format) * transfer->stride + + transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + } +} + +static void r300_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer *transfer) +{ + struct r300_transfer *r300transfer = r300_transfer(transfer); + struct r300_texture *tex = (struct r300_texture*)transfer->texture; + + if (r300transfer->detiled_texture) { + pipe_buffer_unmap(ctx->screen, r300transfer->detiled_texture->buffer); + } else { + pipe_buffer_unmap(ctx->screen, tex->buffer); + } +} + + +void r300_init_transfer_functions( struct r300_context *r300ctx ) +{ + struct pipe_context *ctx = &r300ctx->context; + + ctx->get_tex_transfer = r300_get_tex_transfer; + ctx->tex_transfer_destroy = r300_tex_transfer_destroy; + ctx->transfer_map = r300_transfer_map; + ctx->transfer_unmap = r300_transfer_unmap; +} diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h new file mode 100644 index 00000000000..79baf6d0480 --- /dev/null +++ b/src/gallium/drivers/r300/r300_transfer.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2010 Marek Olšák <[email protected]> + * + * 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 + * on 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 + * THE AUTHOR(S) AND/OR THEIR 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 R300_TRANSFER +#define R300_TRANSFER + +#include "pipe/p_screen.h" + +struct r300_context; + +void r300_init_transfer_functions(struct r300_context *r300ctx); + +#endif diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 60a04bbfeda..379939ac750 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -89,95 +89,41 @@ static void r300_shader_read_vs_outputs( assert(0); } } + + /* WPOS is a straight copy of POSITION and it's always emitted. */ + vs_outputs->wpos = i; } -static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) +/* This function sets up: + * - VAP mapping, which maps VS registers to output semantics and + * at the same time it indicates which attributes are enabled and should + * be rasterized. + * - Stream mapping to VS outputs if TCL is not present. */ +static void r300_init_vs_output_mapping(struct r300_vertex_shader* vs) { struct r300_shader_semantics* vs_outputs = &vs->outputs; - uint32_t* hwfmt = vs->hwfmt; - int i, gen_count; + struct r300_vap_output_state *vap_out = &vs->vap_out; + int *stream_loc = vs->stream_loc_notcl; + int i, gen_count, tabi = 0; boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || vs_outputs->bcolor[1] != ATTR_UNUSED; - /* Do the actual vertex_info setup. - * - * vertex_info has four uints of hardware-specific data in it. - * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL - * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM - * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0 - * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */ - - hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */ + vap_out->vap_vtx_state_cntl = 0x5555; /* XXX this is classic Mesa bonghits */ /* Position. */ if (vs_outputs->pos != ATTR_UNUSED) { - hwfmt[1] |= R300_INPUT_CNTL_POS; - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_POS; + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + + stream_loc[tabi++] = 0; } else { assert(0); } /* Point size. */ if (vs_outputs->psize != ATTR_UNUSED) { - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; - } - - /* Colors. */ - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || - vs_outputs->color[1] != ATTR_UNUSED) { - hwfmt[1] |= R300_INPUT_CNTL_COLOR; - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; - } - } - - /* Back-face colors. */ - if (any_bcolor_used) { - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - hwfmt[1] |= R300_INPUT_CNTL_COLOR; - hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); - } - } + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; - /* Texture coordinates. */ - gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { - hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); - hwfmt[3] |= (4 << (3 * gen_count)); - gen_count++; - } - } - - /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { - hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); - hwfmt[3] |= (4 << (3 * gen_count)); - gen_count++; - } - - /* XXX magic */ - assert(gen_count <= 8); - - /* WPOS. */ - vs->wpos_tex_output = gen_count; -} - -/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed - * or isn't present. */ -static void r300_stream_locations_notcl( - struct r300_shader_semantics* vs_outputs, - int* stream_loc) -{ - int i, tabi = 0, gen_count; - boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || - vs_outputs->bcolor[1] != ATTR_UNUSED; - - /* Position. */ - stream_loc[tabi++] = 0; - - /* Point size. */ - if (vs_outputs->psize != ATTR_UNUSED) { stream_loc[tabi++] = 1; } @@ -185,6 +131,9 @@ static void r300_stream_locations_notcl( for (i = 0; i < ATTR_COLOR_COUNT; i++) { if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || vs_outputs->color[1] != ATTR_UNUSED) { + vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; + stream_loc[tabi++] = 2 + i; } } @@ -192,6 +141,9 @@ static void r300_stream_locations_notcl( /* Back-face colors. */ if (any_bcolor_used) { for (i = 0; i < ATTR_COLOR_COUNT; i++) { + vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR; + vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); + stream_loc[tabi++] = 4 + i; } } @@ -200,6 +152,9 @@ static void r300_stream_locations_notcl( gen_count = 0; for (i = 0; i < ATTR_GENERIC_COUNT; i++) { if (vs_outputs->generic[i] != ATTR_UNUSED) { + vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count); + vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count)); + assert(tabi < 16); stream_loc[tabi++] = 6 + gen_count; gen_count++; @@ -208,17 +163,22 @@ static void r300_stream_locations_notcl( /* Fog coordinates. */ if (vs_outputs->fog != ATTR_UNUSED) { + vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count); + vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count)); + assert(tabi < 16); stream_loc[tabi++] = 6 + gen_count; gen_count++; } + /* XXX magic */ + assert(gen_count <= 8); + /* WPOS. */ - if (vs_outputs->wpos != ATTR_UNUSED) { - assert(tabi < 16); - stream_loc[tabi++] = 6 + gen_count; - gen_count++; - } + vs->wpos_tex_output = gen_count; + + assert(tabi < 16); + stream_loc[tabi++] = 6 + gen_count; for (; tabi < 16;) { stream_loc[tabi++] = -1; @@ -294,26 +254,16 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) } } -static void r300_insert_wpos(struct r300_vertex_program_compiler* c, - struct r300_shader_semantics* outputs) +void r300_vertex_shader_common_init(struct r300_vertex_shader *vs, + const struct pipe_shader_state *shader) { - int i, lastOutput = 0; - - /* Find the max output index. */ - lastOutput = MAX2(lastOutput, outputs->psize); - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - lastOutput = MAX2(lastOutput, outputs->color[i]); - lastOutput = MAX2(lastOutput, outputs->bcolor[i]); - } - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - lastOutput = MAX2(lastOutput, outputs->generic[i]); - } - lastOutput = MAX2(lastOutput, outputs->fog); + /* Copy state directly into shader. */ + vs->state = *shader; + vs->state.tokens = tgsi_dup_tokens(shader->tokens); + tgsi_scan_shader(shader->tokens, &vs->info); - /* Set WPOS after the last output. */ - lastOutput++; - rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */ - outputs->wpos = lastOutput; + r300_shader_read_vs_outputs(&vs->info, &vs->outputs); + r300_init_vs_output_mapping(vs); } void r300_translate_vertex_shader(struct r300_context* r300, @@ -322,9 +272,6 @@ void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; - /* Initialize. */ - r300_shader_read_vs_outputs(&vs->info, &vs->outputs); - /* Setup the compiler */ rc_init(&compiler.Base); @@ -348,10 +295,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ - r300_insert_wpos(&compiler, &vs->outputs); - - r300_shader_vap_output_fmt(vs); - r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl); + rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); /* Invoke the compiler */ r3xx_compile_vertex_program(&compiler); @@ -363,30 +307,29 @@ void r300_translate_vertex_shader(struct r300_context* r300, /* And, finally... */ rc_destroy(&compiler.Base); - vs->translated = TRUE; } boolean r300_vertex_shader_setup_wpos(struct r300_context* r300) { struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_vap_output_state *vap_out = &vs->vap_out; int tex_output = vs->wpos_tex_output; uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; - uint32_t* hwfmt = vs->hwfmt; if (r300->fs->inputs.wpos != ATTR_UNUSED) { /* Enable WPOS in VAP. */ - if (!(hwfmt[1] & tex_fmt)) { - hwfmt[1] |= tex_fmt; - hwfmt[3] |= (4 << (3 * tex_output)); + if (!(vap_out->vap_vsm_vtx_assm & tex_fmt)) { + vap_out->vap_vsm_vtx_assm |= tex_fmt; + vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * tex_output)); assert(tex_output < 8); return TRUE; } } else { /* Disable WPOS in VAP. */ - if (hwfmt[1] & tex_fmt) { - hwfmt[1] &= ~tex_fmt; - hwfmt[3] &= ~(4 << (3 * tex_output)); + if (vap_out->vap_vsm_vtx_assm & tex_fmt) { + vap_out->vap_vsm_vtx_assm &= ~tex_fmt; + vap_out->vap_out_vtx_fmt[1] &= ~(4 << (3 * tex_output)); return TRUE; } } diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 18cfeee3cd4..f6f0b86b683 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -28,6 +28,7 @@ #include "tgsi/tgsi_scan.h" #include "radeon_code.h" +#include "r300_context.h" #include "r300_shader_semantics.h" struct r300_context; @@ -38,7 +39,7 @@ struct r300_vertex_shader { struct tgsi_shader_info info; struct r300_shader_semantics outputs; - uint hwfmt[4]; + struct r300_vap_output_state vap_out; /* Stream locations for SWTCL or if TCL is bypassed. */ int stream_loc_notcl[16]; @@ -46,13 +47,17 @@ struct r300_vertex_shader { /* Output stream location for WPOS. */ int wpos_tex_output; - /* Has this shader been translated yet? */ - boolean translated; - + /* HWTCL-specific. */ /* Machine code (if translated) */ struct r300_vertex_program_code code; + + /* SWTCL-specific. */ + void *draw_vs; }; +void r300_vertex_shader_common_init(struct r300_vertex_shader *vs, + const struct pipe_shader_state *shader); + void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 40fb8a95ca5..ddf2b790039 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -40,11 +40,6 @@ struct radeon_winsys; struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct pipe_buffer** buffer, - unsigned* stride); - #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index e4ac49fa85f..239655d628b 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -6,7 +6,9 @@ LIBNAME = softpipe C_SOURCES = \ sp_fs_exec.c \ sp_fs_sse.c \ + sp_buffer.c \ sp_clear.c \ + sp_fence.c \ sp_flush.c \ sp_query.c \ sp_context.c \ @@ -32,7 +34,6 @@ C_SOURCES = \ sp_tex_tile_cache.c \ sp_tile_cache.c \ sp_surface.c \ - sp_video_context.c \ - sp_winsys.c + sp_video_context.c include ../../Makefile.template diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index 3042e556c64..9949a53adfd 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -7,9 +7,11 @@ softpipe = env.ConvenienceLibrary( source = [ 'sp_fs_exec.c', 'sp_fs_sse.c', + 'sp_buffer.c', 'sp_clear.c', 'sp_context.c', 'sp_draw_arrays.c', + 'sp_fence.c', 'sp_flush.c', 'sp_prim_vbuf.c', 'sp_setup.c', @@ -33,8 +35,7 @@ softpipe = env.ConvenienceLibrary( 'sp_tex_tile_cache.c', 'sp_texture.c', 'sp_tile_cache.c', - 'sp_video_context.c', - 'sp_winsys.c' + 'sp_video_context.c' ]) Export('softpipe') diff --git a/src/gallium/drivers/softpipe/sp_buffer.c b/src/gallium/drivers/softpipe/sp_buffer.c new file mode 100644 index 00000000000..8f390250869 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_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 "sp_screen.h" +#include "sp_buffer.h" + + +static void * +softpipe_buffer_map(struct pipe_screen *screen, + struct pipe_buffer *buf, + unsigned flags) +{ + struct softpipe_buffer *softpipe_buf = softpipe_buffer(buf); + return softpipe_buf->data; +} + + +static void +softpipe_buffer_unmap(struct pipe_screen *screen, + struct pipe_buffer *buf) +{ +} + + +static void +softpipe_buffer_destroy(struct pipe_buffer *buf) +{ + struct softpipe_buffer *sbuf = softpipe_buffer(buf); + + if (!sbuf->userBuffer) + align_free(sbuf->data); + + FREE(sbuf); +} + + +static struct pipe_buffer * +softpipe_buffer_create(struct pipe_screen *screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct softpipe_buffer *buffer = CALLOC_STRUCT(softpipe_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 * +softpipe_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes) +{ + struct softpipe_buffer *buffer; + + buffer = CALLOC_STRUCT(softpipe_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 +softpipe_init_screen_buffer_funcs(struct pipe_screen *screen) +{ + screen->buffer_create = softpipe_buffer_create; + screen->user_buffer_create = softpipe_user_buffer_create; + screen->buffer_map = softpipe_buffer_map; + screen->buffer_unmap = softpipe_buffer_unmap; + screen->buffer_destroy = softpipe_buffer_destroy; +} diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_buffer.h index 6e3920c49b2..9d8e56a176b 100644 --- a/src/gallium/drivers/softpipe/sp_winsys.h +++ b/src/gallium/drivers/softpipe/sp_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,64 +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. - * + * **************************************************************************/ -/* This is the interface that softpipe requires any window system - * hosting it to implement. This is the only include file in softpipe - * which is public. - */ +#ifndef SP_BUFFER_H +#define SP_BUFFER_H +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" -#ifndef SP_WINSYS_H -#define SP_WINSYS_H -#ifdef __cplusplus -extern "C" { -#endif +struct softpipe_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; +}; -#include "pipe/p_defines.h" -struct pipe_screen; -struct pipe_winsys; -struct pipe_context; -struct pipe_texture; -struct pipe_buffer; - - - -/** - * Create a softpipe screen that uses the - * given winsys for allocating buffers. - */ -struct pipe_screen *softpipe_create_screen( struct pipe_winsys * ); - -/** - * Create a softpipe screen that uses - * regular malloc to create all its buffers. - */ -struct pipe_screen *softpipe_create_screen_malloc(void); +/** Cast wrapper */ +static INLINE struct softpipe_buffer * +softpipe_buffer( struct pipe_buffer *buf ) +{ + return (struct softpipe_buffer *)buf; +} -boolean -softpipe_get_texture_buffer( struct pipe_texture *texture, - struct pipe_buffer **buf, - unsigned *stride ); +void +softpipe_init_screen_buffer_funcs(struct pipe_screen *screen); -#ifdef __cplusplus -} -#endif -#endif /* SP_WINSYS_H */ +#endif /* SP_BUFFER_H */ diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index ddc35bcd629..de92a0cd2c7 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -44,6 +44,7 @@ #include "sp_surface.h" #include "sp_tile_cache.h" #include "sp_tex_tile_cache.h" +#include "sp_texture.h" #include "sp_query.h" @@ -210,7 +211,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE ); softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE ); - softpipe->pipe.winsys = screen->winsys; + softpipe->pipe.winsys = NULL; softpipe->pipe.screen = screen; softpipe->pipe.destroy = softpipe_destroy; softpipe->pipe.priv = priv; @@ -245,6 +246,10 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.bind_gs_state = softpipe_bind_gs_state; softpipe->pipe.delete_gs_state = softpipe_delete_gs_state; + softpipe->pipe.create_vertex_elements_state = softpipe_create_vertex_elements_state; + softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state; + softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state; + softpipe->pipe.set_blend_color = softpipe_set_blend_color; softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref; softpipe->pipe.set_clip_state = softpipe_set_clip_state; @@ -257,7 +262,6 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers; - softpipe->pipe.set_vertex_elements = softpipe_set_vertex_elements; softpipe->pipe.draw_arrays = softpipe_draw_arrays; softpipe->pipe.draw_elements = softpipe_draw_elements; @@ -272,6 +276,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.is_buffer_referenced = softpipe_is_buffer_referenced; softpipe_init_query_funcs( softpipe ); + softpipe_init_texture_funcs( &softpipe->pipe ); softpipe->pipe.render_condition = softpipe_render_condition; @@ -280,13 +285,13 @@ softpipe_create_context( struct pipe_screen *screen, * Must be before quad stage setup! */ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) - softpipe->cbuf_cache[i] = sp_create_tile_cache( screen ); - softpipe->zsbuf_cache = sp_create_tile_cache( screen ); + softpipe->cbuf_cache[i] = sp_create_tile_cache( &softpipe->pipe ); + softpipe->zsbuf_cache = sp_create_tile_cache( &softpipe->pipe ); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) - softpipe->tex_cache[i] = sp_create_tex_tile_cache( screen ); + softpipe->tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache(screen); + softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); } /* setup quad rendering stages */ diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 95def72c541..9a8158e6a22 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -45,6 +45,7 @@ struct softpipe_tile_cache; struct softpipe_tex_tile_cache; struct sp_fragment_shader; struct sp_vertex_shader; +struct sp_velems_state; struct softpipe_context { @@ -59,6 +60,7 @@ struct softpipe_context { struct sp_fragment_shader *fs; struct sp_vertex_shader *vs; struct sp_geometry_shader *gs; + struct sp_velems_state *velems; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -72,13 +74,11 @@ struct softpipe_context { struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; unsigned num_samplers; unsigned num_textures; unsigned num_vertex_samplers; unsigned num_vertex_textures; - unsigned num_vertex_elements; unsigned num_vertex_buffers; unsigned dirty; /**< Mask of SP_NEW_x flags */ @@ -93,7 +93,7 @@ struct softpipe_context { ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; /** Mapped constant buffers */ - void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; + const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; /** Vertex format */ struct vertex_info vertex_info; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index b2acc36bf7a..7b77eb239fd 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -33,90 +33,19 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" #include "util/u_prim.h" #include "sp_context.h" #include "sp_query.h" #include "sp_state.h" +#include "sp_buffer.h" #include "draw/draw_context.h" -static void -softpipe_map_constant_buffers(struct softpipe_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - uint j; - - for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { - if (sp->constants[i][j] && sp->constants[i][j]->size) { - sp->mapped_constants[i][j] = ws->buffer_map(ws, - sp->constants[i][j], - PIPE_BUFFER_USAGE_CPU_READ); - } - } - } - - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - if (sp->constants[PIPE_SHADER_VERTEX][i]) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_VERTEX, - i, - sp->mapped_constants[PIPE_SHADER_VERTEX][i], - sp->constants[PIPE_SHADER_VERTEX][i]->size); - } - if (sp->constants[PIPE_SHADER_GEOMETRY][i]) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_GEOMETRY, - i, - sp->mapped_constants[PIPE_SHADER_GEOMETRY][i], - sp->constants[PIPE_SHADER_GEOMETRY][i]->size); - } - } -} - - -static void -softpipe_unmap_constant_buffers(struct softpipe_context *sp) -{ - struct pipe_winsys *ws = sp->pipe.winsys; - uint i; - /* really need to flush all prims since the vert/frag shaders const buffers - * are going away now. - */ - draw_flush(sp->draw); - - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_VERTEX, - i, - NULL, - 0); - draw_set_mapped_constant_buffer(sp->draw, - PIPE_SHADER_GEOMETRY, - i, - NULL, - 0); - } - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - uint j; - - for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { - if (sp->constants[i][j] && sp->constants[i][j]->size) { - ws->buffer_unmap(ws, sp->constants[i][j]); - } - sp->mapped_constants[i][j] = NULL; - } - } -} /** @@ -261,25 +190,16 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, } softpipe_map_transfers(sp); - softpipe_map_constant_buffers(sp); /* Map vertex buffers */ for (i = 0; i < sp->num_vertex_buffers; i++) { - void *buf; - - buf = pipe_buffer_map(pipe->screen, - sp->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *buf = softpipe_buffer(sp->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { - void *mapped_indexes; - - mapped_indexes = pipe_buffer_map(pipe->screen, - indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *mapped_indexes = softpipe_buffer(indexBuffer)->data; draw_set_mapped_element_buffer_range(draw, indexSize, minIndex, @@ -300,15 +220,18 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->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 */ - softpipe_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); + /* Note: leave drawing surfaces mapped */ sp->dirty_render_cache = TRUE; } diff --git a/src/gallium/drivers/softpipe/sp_fence.c b/src/gallium/drivers/softpipe/sp_fence.c new file mode 100644 index 00000000000..66c52141132 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_fence.c @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2010 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#include "pipe/p_screen.h" +#include "util/u_debug.h" +#include "sp_fence.h" + + +static void +softpipe_fence_reference(struct pipe_screen *screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + assert(!*ptr); + assert(!fence); +} + + +static int +softpipe_fence_signalled(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + assert(!fence); + return 0; +} + + +static int +softpipe_fence_finish(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + assert(!fence); + return 0; +} + + +void +softpipe_init_screen_fence_funcs(struct pipe_screen *screen) +{ + screen->fence_reference = softpipe_fence_reference; + screen->fence_finish = softpipe_fence_finish; + screen->fence_signalled = softpipe_fence_signalled; +} diff --git a/src/gallium/drivers/softpipe/sp_fence.h b/src/gallium/drivers/softpipe/sp_fence.h new file mode 100644 index 00000000000..39c33243bd5 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_fence.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2010 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#ifndef SP_FENCE_H_ +#define SP_FENCE_H_ + + +struct pipe_screen; + + +void +softpipe_init_screen_fence_funcs(struct pipe_screen *screen); + + +#endif /* SP_FENCE_H_ */ diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index e8952bf4fb8..3d76af4d8cb 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -93,9 +93,9 @@ softpipe_flush( struct pipe_context *pipe, static unsigned frame_no = 1; static char filename[256]; util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no); - debug_dump_surface_bmp(filename, softpipe->framebuffer.cbufs[0]); + debug_dump_surface_bmp(softpipe, filename, softpipe->framebuffer.cbufs[0]); util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no); - debug_dump_surface_bmp(filename, softpipe->framebuffer.zsbuf); + debug_dump_surface_bmp(softpipe, filename, softpipe->framebuffer.zsbuf); ++frame_no; } #endif diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c index 27fa126b7c3..67e2c8f8bc4 100644 --- a/src/gallium/drivers/softpipe/sp_fs_exec.c +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c @@ -145,8 +145,13 @@ exec_run( const struct sp_fragment_shader *base, case TGSI_SEMANTIC_COLOR: { uint cbuf = sem_index[i]; + + assert(sizeof(quad->output.color[cbuf]) == + sizeof(machine->Outputs[i])); + + /* copy float[4][4] result */ memcpy(quad->output.color[cbuf], - &machine->Outputs[i].xyzw[0].f[0], + &machine->Outputs[i], sizeof(quad->output.color[0]) ); } break; diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index acee2136706..daa158df7c4 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -156,8 +156,13 @@ fs_sse_run( const struct sp_fragment_shader *base, case TGSI_SEMANTIC_COLOR: { uint cbuf = sem_index[i]; + + assert(sizeof(quad->output.color[cbuf]) == + sizeof(machine->Outputs[i])); + + /* copy float[4][4] result */ memcpy(quad->output.color[cbuf], - &machine->Outputs[i].xyzw[0].f[0], + &machine->Outputs[i], sizeof(quad->output.color[0]) ); } break; diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index 98c08eaffaf..6749243ab41 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -264,57 +264,29 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - } } break; case PIPE_PRIM_QUAD_STRIP: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride)); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-3], stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-3], stride), get_vert(vertex_buffer, indices[i-0], stride) ); - } } break; @@ -448,56 +420,28 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-3, stride), get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); - } } break; case PIPE_PRIM_QUAD_STRIP: - if (softpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-3, stride) ); - } - } - else { - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-3, stride), get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, + sp_setup_tri( setup_ctx, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-3, stride), get_vert(vertex_buffer, i-0, stride) ); - } } break; diff --git a/src/gallium/drivers/softpipe/sp_public.h b/src/gallium/drivers/softpipe/sp_public.h new file mode 100644 index 00000000000..62d0903d87a --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_public.h @@ -0,0 +1,10 @@ +#ifndef SP_PUBLIC_H +#define SP_PUBLIC_H + +struct pipe_screen; +struct sw_winsys; + +struct pipe_screen * +softpipe_create_screen(struct sw_winsys *winsys); + +#endif diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 6ec63fe698a..d62bfa3d633 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -27,15 +27,17 @@ #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" +#include "state_tracker/sw_winsys.h" + #include "sp_texture.h" -#include "sp_winsys.h" #include "sp_screen.h" #include "sp_context.h" +#include "sp_buffer.h" +#include "sp_fence.h" +#include "sp_public.h" static const char * @@ -83,11 +85,11 @@ softpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 13; /* max 4Kx4K */ + return SP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 9; /* max 256x256x256 */ + return SP_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 13; /* max 4Kx4K */ + return SP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: @@ -145,6 +147,8 @@ softpipe_is_format_supported( struct pipe_screen *screen, unsigned tex_usage, unsigned geom_flags ) { + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + assert(target == PIPE_TEXTURE_1D || target == PIPE_TEXTURE_2D || target == PIPE_TEXTURE_3D || @@ -166,15 +170,25 @@ softpipe_is_format_supported( struct pipe_screen *screen, case PIPE_FORMAT_NONE: return FALSE; default: - return TRUE; + break; } + + if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + if(!winsys->is_displaytarget_format_supported(winsys, format)) + return FALSE; + } + + /* XXX: this is often a lie. Pull in logic from llvmpipe to fix. + */ + return TRUE; } static void softpipe_destroy_screen( struct pipe_screen *screen ) { - struct pipe_winsys *winsys = screen->winsys; + struct softpipe_screen *sp_screen = softpipe_screen(screen); + struct sw_winsys *winsys = sp_screen->winsys; if(winsys->destroy) winsys->destroy(winsys); @@ -183,21 +197,37 @@ softpipe_destroy_screen( struct pipe_screen *screen ) } +/* This is often overriden by the co-state tracker. + */ +static void +softpipe_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *surface, + void *context_private) +{ + struct softpipe_screen *screen = softpipe_screen(_screen); + struct sw_winsys *winsys = screen->winsys; + struct softpipe_texture *texture = softpipe_texture(surface->texture); + + assert(texture->dt); + if (texture->dt) + winsys->displaytarget_display(winsys, texture->dt, context_private); +} /** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no softpipe_screen). */ struct pipe_screen * -softpipe_create_screen(struct pipe_winsys *winsys) +softpipe_create_screen(struct sw_winsys *winsys) { struct softpipe_screen *screen = CALLOC_STRUCT(softpipe_screen); if (!screen) return NULL; - screen->base.winsys = winsys; + screen->winsys = winsys; + screen->base.winsys = NULL; screen->base.destroy = softpipe_destroy_screen; screen->base.get_name = softpipe_get_name; @@ -206,9 +236,11 @@ softpipe_create_screen(struct pipe_winsys *winsys) screen->base.get_paramf = softpipe_get_paramf; screen->base.is_format_supported = softpipe_is_format_supported; screen->base.context_create = softpipe_create_context; + screen->base.flush_frontbuffer = softpipe_flush_frontbuffer; softpipe_init_screen_texture_funcs(&screen->base); - u_simple_screen_init(&screen->base); + softpipe_init_screen_buffer_funcs(&screen->base); + softpipe_init_screen_fence_funcs(&screen->base); return &screen->base; } diff --git a/src/gallium/drivers/softpipe/sp_screen.h b/src/gallium/drivers/softpipe/sp_screen.h index 3d4bfd3e840..f741454c9e5 100644 --- a/src/gallium/drivers/softpipe/sp_screen.h +++ b/src/gallium/drivers/softpipe/sp_screen.h @@ -35,10 +35,13 @@ #include "pipe/p_defines.h" +struct sw_winsys; struct softpipe_screen { struct pipe_screen base; + struct sw_winsys *winsys; + /* Increments whenever textures are modified. Contexts can track * this. */ @@ -55,4 +58,5 @@ softpipe_screen( struct pipe_screen *pipe ) } + #endif /* SP_SCREEN_H */ diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 4370bbeaee2..6b01c0f4d72 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -100,6 +100,11 @@ struct sp_geometry_shader { struct draw_geometry_shader *draw_data; }; +struct sp_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; + void * softpipe_create_blend_state(struct pipe_context *, @@ -160,8 +165,14 @@ void *softpipe_create_gs_state(struct pipe_context *, void softpipe_bind_gs_state(struct pipe_context *, void *); void softpipe_delete_gs_state(struct pipe_context *, void *); +void *softpipe_create_vertex_elements_state(struct pipe_context *, + unsigned count, + const struct pipe_vertex_element *); +void softpipe_bind_vertex_elements_state(struct pipe_context *, void *); +void softpipe_delete_vertex_elements_state(struct pipe_context *, void *); + void softpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); + const struct pipe_poly_stipple * ); void softpipe_set_scissor_state( struct pipe_context *, const struct pipe_scissor_state * ); @@ -178,10 +189,6 @@ softpipe_set_vertex_sampler_textures(struct pipe_context *, void softpipe_set_viewport_state( struct pipe_context *, const struct pipe_viewport_state * ); -void softpipe_set_vertex_elements(struct pipe_context *, - unsigned count, - const struct pipe_vertex_element *); - void softpipe_set_vertex_buffers(struct pipe_context *, unsigned count, const struct pipe_vertex_buffer *); diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index c88e2137510..2b089c28316 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -28,6 +28,7 @@ #include "sp_context.h" #include "sp_state.h" #include "sp_fs.h" +#include "sp_buffer.h" #include "pipe/p_defines.h" #include "util/u_memory.h" @@ -163,26 +164,33 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) FREE( state ); } - - void softpipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_buffer *constants) { struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned size = constants ? constants->size : 0; + const void *data = constants ? softpipe_buffer(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); - assert(index < PIPE_MAX_CONSTANT_BUFFERS); + assert(index == 0); draw_flush(softpipe->draw); /* note: reference counting */ - pipe_buffer_reference(&softpipe->constants[shader][index], buf); + pipe_buffer_reference(&softpipe->constants[shader][index], constants); + if(shader == PIPE_SHADER_VERTEX) { + draw_set_mapped_constant_buffer(softpipe->draw, PIPE_SHADER_VERTEX, index, + data, size); + } + + softpipe->mapped_constants[shader][index] = data; softpipe->dirty |= SP_NEW_CONSTANTS; } + void * softpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index b491d92ed15..462f4d2655e 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -32,27 +32,45 @@ #include "sp_context.h" #include "sp_state.h" +#include "util/u_memory.h" #include "draw/draw_context.h" +void * +softpipe_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) +{ + struct sp_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct sp_velems_state *) MALLOC(sizeof(struct sp_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} + void -softpipe_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *attribs) +softpipe_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) { struct softpipe_context *softpipe = softpipe_context(pipe); + struct sp_velems_state *sp_velems = (struct sp_velems_state *) velems; - assert(count <= PIPE_MAX_ATTRIBS); - - memcpy(softpipe->vertex_element, attribs, - count * sizeof(struct pipe_vertex_element)); - softpipe->num_vertex_elements = count; + softpipe->velems = sp_velems; softpipe->dirty |= SP_NEW_VERTEX; - draw_set_vertex_elements(softpipe->draw, count, attribs); + if (sp_velems) + draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem); } +void +softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) +{ + FREE( velems ); +} void softpipe_set_vertex_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index ef7ccf41898..fa9e19b282b 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -1614,7 +1614,6 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); unsigned j; float ssss[4], tttt[4]; - unsigned face; /* major axis @@ -1628,7 +1627,8 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz */ - /* First choose the cube face. + /* Choose the cube face and compute new s/t coords for the 2D face. + * * Use the same cube face for all four pixels in the quad. * * This isn't ideal, but if we want to use a different cube face @@ -1647,85 +1647,37 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); if (arx >= ary && arx >= arz) { - if (rx >= 0.0F) { - face = PIPE_TEX_FACE_POS_X; - } - else { - face = PIPE_TEX_FACE_NEG_X; + float sign = (rx >= 0.0F) ? 1.0F : -1.0F; + uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X; + for (j = 0; j < QUAD_SIZE; j++) { + const float ima = -0.5F / fabsf(s[j]); + ssss[j] = sign * p[j] * ima + 0.5F; + tttt[j] = t[j] * ima + 0.5F; + samp->faces[j] = face; } } else if (ary >= arx && ary >= arz) { - if (ry >= 0.0F) { - face = PIPE_TEX_FACE_POS_Y; - } - else { - face = PIPE_TEX_FACE_NEG_Y; + float sign = (ry >= 0.0F) ? 1.0F : -1.0F; + uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y; + for (j = 0; j < QUAD_SIZE; j++) { + const float ima = -0.5F / fabsf(t[j]); + ssss[j] = -s[j] * ima + 0.5F; + tttt[j] = sign * -p[j] * ima + 0.5F; + samp->faces[j] = face; } } else { - if (rz > 0.0F) { - face = PIPE_TEX_FACE_POS_Z; - } - else { - face = PIPE_TEX_FACE_NEG_Z; + float sign = (rz >= 0.0F) ? 1.0F : -1.0F; + uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z; + for (j = 0; j < QUAD_SIZE; j++) { + const float ima = -0.5 / fabsf(p[j]); + ssss[j] = sign * -s[j] * ima + 0.5F; + tttt[j] = t[j] * ima + 0.5F; + samp->faces[j] = face; } } } - /* Now compute the 2D _face_ texture coords from the - * 3D _cube_ texture coords. - */ - for (j = 0; j < QUAD_SIZE; j++) { - const float rx = s[j], ry = t[j], rz = p[j]; - const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); - float sc, tc, ma; - - switch (face) { - case PIPE_TEX_FACE_POS_X: - sc = -rz; - tc = -ry; - ma = arx; - break; - case PIPE_TEX_FACE_NEG_X: - sc = rz; - tc = -ry; - ma = arx; - break; - case PIPE_TEX_FACE_POS_Y: - sc = rx; - tc = rz; - ma = ary; - break; - case PIPE_TEX_FACE_NEG_Y: - sc = rx; - tc = -rz; - ma = ary; - break; - case PIPE_TEX_FACE_POS_Z: - sc = rx; - tc = -ry; - ma = arz; - break; - case PIPE_TEX_FACE_NEG_Z: - sc = -rx; - tc = -ry; - ma = arz; - break; - default: - assert(0 && "bad cube face"); - sc = 0.0F; - tc = 0.0F; - ma = 0.0F; - } - - { - const float ima = 1.0 / ma; - ssss[j] = ( sc * ima + 1.0F ) * 0.5F; - tttt[j] = ( tc * ima + 1.0F ) * 0.5F; - samp->faces[j] = face; - } - } - /* In our little pipeline, the compare stage is next. If compare * is not active, this will point somewhere deeper into the * pipeline, eg. to mip_filter or even img_filter. diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index a0b95c88846..e3a5e37ce44 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -43,14 +43,14 @@ struct softpipe_tex_tile_cache * -sp_create_tex_tile_cache( struct pipe_screen *screen ) +sp_create_tex_tile_cache( struct pipe_context *pipe ) { struct softpipe_tex_tile_cache *tc; uint pos; tc = CALLOC_STRUCT( softpipe_tex_tile_cache ); if (tc) { - tc->screen = screen; + tc->pipe = pipe; for (pos = 0; pos < NUM_ENTRIES; pos++) { tc->entries[pos].addr.bits.invalid = 1; } @@ -63,19 +63,16 @@ sp_create_tex_tile_cache( struct pipe_screen *screen ) void sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc) { - struct pipe_screen *screen; uint pos; for (pos = 0; pos < NUM_ENTRIES; pos++) { /*assert(tc->entries[pos].x < 0);*/ } if (tc->transfer) { - screen = tc->transfer->texture->screen; - screen->tex_transfer_destroy(tc->transfer); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->transfer); } if (tc->tex_trans) { - screen = tc->tex_trans->texture->screen; - screen->tex_transfer_destroy(tc->tex_trans); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->tex_trans); } FREE( tc ); @@ -88,7 +85,7 @@ void sp_tex_tile_cache_map_transfers(struct softpipe_tex_tile_cache *tc) { if (tc->tex_trans && !tc->tex_trans_map) - tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans); + tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); } @@ -96,7 +93,7 @@ void sp_tex_tile_cache_unmap_transfers(struct softpipe_tex_tile_cache *tc) { if (tc->tex_trans_map) { - tc->screen->transfer_unmap(tc->screen, tc->tex_trans); + tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } } @@ -133,14 +130,12 @@ sp_tex_tile_cache_set_texture(struct softpipe_tex_tile_cache *tc, pipe_texture_reference(&tc->texture, texture); if (tc->tex_trans) { - struct pipe_screen *screen = tc->tex_trans->texture->screen; - if (tc->tex_trans_map) { - screen->transfer_unmap(screen, tc->tex_trans); + tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } - screen->tex_transfer_destroy(tc->tex_trans); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->tex_trans); tc->tex_trans = NULL; } @@ -204,7 +199,6 @@ const struct softpipe_tex_cached_tile * sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, union tex_tile_address addr ) { - struct pipe_screen *screen = tc->screen; struct softpipe_tex_cached_tile *tile; tile = tc->entries + tex_cache_pos( addr ); @@ -232,16 +226,16 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, if (tc->tex_trans) { if (tc->tex_trans_map) { - tc->screen->transfer_unmap(tc->screen, tc->tex_trans); + tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans); tc->tex_trans_map = NULL; } - screen->tex_transfer_destroy(tc->tex_trans); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->tex_trans); tc->tex_trans = NULL; } tc->tex_trans = - screen->get_tex_transfer(screen, tc->texture, + tc->pipe->get_tex_transfer(tc->pipe, tc->texture, addr.bits.face, addr.bits.level, addr.bits.z, @@ -249,7 +243,7 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, u_minify(tc->texture->width0, addr.bits.level), u_minify(tc->texture->height0, addr.bits.level)); - tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans); + tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans); tc->tex_face = addr.bits.face; tc->tex_level = addr.bits.level; @@ -257,7 +251,8 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, } /* get tile from the transfer (view into texture) */ - pipe_get_tile_rgba(tc->tex_trans, + pipe_get_tile_rgba(tc->pipe, + tc->tex_trans, addr.bits.x * TILE_SIZE, addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h index ac6886a3df1..b1163972587 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h @@ -70,7 +70,7 @@ struct softpipe_tex_cached_tile struct softpipe_tex_tile_cache { - struct pipe_screen *screen; + struct pipe_context *pipe; struct pipe_transfer *transfer; void *transfer_map; @@ -88,7 +88,7 @@ struct softpipe_tex_tile_cache extern struct softpipe_tex_tile_cache * -sp_create_tex_tile_cache( struct pipe_screen *screen ); +sp_create_tex_tile_cache( struct pipe_context *pipe ); extern void sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc); diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 32d261b5ffc..da8529c154e 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -36,11 +36,13 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_simple_screen.h" #include "sp_context.h" #include "sp_texture.h" #include "sp_screen.h" -#include "sp_winsys.h" + +#include "state_tracker/sw_winsys.h" /** @@ -72,11 +74,9 @@ softpipe_texture_layout(struct pipe_screen *screen, depth = u_minify(depth, 1); } - spt->buffer = screen->buffer_create(screen, 32, - PIPE_BUFFER_USAGE_PIXEL, - buffer_size); + spt->data = align_malloc(buffer_size, 16); - return spt->buffer != NULL; + return spt->data != NULL; } @@ -87,19 +87,18 @@ static boolean softpipe_displaytarget_layout(struct pipe_screen *screen, struct softpipe_texture * spt) { - unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE | - PIPE_BUFFER_USAGE_GPU_READ_WRITE); - unsigned tex_usage = spt->base.tex_usage; - - spt->buffer = screen->surface_buffer_create( screen, - spt->base.width0, - spt->base.height0, - spt->base.format, - usage, - tex_usage, - &spt->stride[0]); - - return spt->buffer != NULL; + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + + /* Round up the surface size to a multiple of the tile size? + */ + spt->dt = winsys->displaytarget_create(winsys, + spt->base.format, + spt->base.width0, + spt->base.height0, + 16, + &spt->stride[0] ); + + return spt->dt != NULL; } @@ -123,7 +122,8 @@ softpipe_texture_create(struct pipe_screen *screen, util_is_power_of_two(template->depth0)); if (spt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { if (!softpipe_displaytarget_layout(screen, spt)) goto fail; } @@ -140,46 +140,24 @@ softpipe_texture_create(struct pipe_screen *screen, } -/** - * Create a new pipe_texture which wraps an existing buffer. - */ -static struct pipe_texture * -softpipe_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) -{ - struct softpipe_texture *spt; - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - spt = CALLOC_STRUCT(softpipe_texture); - if (!spt) - return NULL; - - spt->base = *base; - pipe_reference_init(&spt->base.reference, 1); - spt->base.screen = screen; - spt->stride[0] = stride[0]; - - pipe_buffer_reference(&spt->buffer, buffer); - - return &spt->base; -} static void softpipe_texture_destroy(struct pipe_texture *pt) { + struct softpipe_screen *screen = softpipe_screen(pt->screen); struct softpipe_texture *spt = softpipe_texture(pt); - pipe_buffer_reference(&spt->buffer, NULL); + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = screen->winsys; + winsys->displaytarget_destroy(winsys, spt->dt); + } + else { + /* regular texture */ + align_free(spt->data); + } + FREE(spt); } @@ -278,7 +256,7 @@ softpipe_tex_surface_destroy(struct pipe_surface *surf) * \param height height of region to read/write */ static struct pipe_transfer * -softpipe_get_tex_transfer(struct pipe_screen *screen, +softpipe_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -332,7 +310,8 @@ softpipe_get_tex_transfer(struct pipe_screen *screen, * softpipe_get_tex_transfer(). */ static void -softpipe_tex_transfer_destroy(struct pipe_transfer *transfer) +softpipe_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is @@ -348,7 +327,7 @@ softpipe_tex_transfer_destroy(struct pipe_transfer *transfer) * Create memory mapping for given pipe_transfer object. */ static void * -softpipe_transfer_map( struct pipe_screen *screen, +softpipe_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { ubyte *map, *xfer_map; @@ -359,9 +338,20 @@ softpipe_transfer_map( struct pipe_screen *screen, spt = softpipe_texture(transfer->texture); format = transfer->texture->format; - map = pipe_buffer_map(screen, spt->buffer, pipe_transfer_buffer_flags(transfer)); - if (map == NULL) - return NULL; + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; + + map = winsys->displaytarget_map(winsys, spt->dt, + pipe_transfer_buffer_flags(transfer)); + if (map == NULL) + return NULL; + } + else { + map = spt->data; + if (map == NULL) + return NULL; + } /* May want to different things here depending on read/write nature * of the map: @@ -370,7 +360,7 @@ softpipe_transfer_map( struct pipe_screen *screen, /* Do something to notify sharing contexts of a texture change. * In softpipe, that would mean flushing the texture cache. */ - softpipe_screen(screen)->timestamp++; + softpipe_screen(pipe->screen)->timestamp++; } xfer_map = map + softpipe_transfer(transfer)->offset + @@ -385,7 +375,7 @@ softpipe_transfer_map( struct pipe_screen *screen, * Unmap memory mapping for given pipe_transfer object. */ static void -softpipe_transfer_unmap(struct pipe_screen *screen, +softpipe_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct softpipe_texture *spt; @@ -393,7 +383,11 @@ softpipe_transfer_unmap(struct pipe_screen *screen, assert(transfer->texture); spt = softpipe_texture(transfer->texture); - pipe_buffer_unmap( screen, spt->buffer ); + if (spt->dt) { + /* display target */ + struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; + winsys->displaytarget_unmap(winsys, spt->dt); + } if (transfer->usage & PIPE_TRANSFER_WRITE) { /* Mark the texture as dirty to expire the tile caches. */ @@ -455,43 +449,26 @@ softpipe_video_surface_destroy(struct pipe_video_surface *vsfc) void +softpipe_init_texture_funcs(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = softpipe_get_tex_transfer; + pipe->tex_transfer_destroy = softpipe_tex_transfer_destroy; + pipe->transfer_map = softpipe_transfer_map; + pipe->transfer_unmap = softpipe_transfer_unmap; +} + +void softpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->texture_create = softpipe_texture_create; - screen->texture_blanket = softpipe_texture_blanket; screen->texture_destroy = softpipe_texture_destroy; screen->get_tex_surface = softpipe_get_tex_surface; screen->tex_surface_destroy = softpipe_tex_surface_destroy; - screen->get_tex_transfer = softpipe_get_tex_transfer; - screen->tex_transfer_destroy = softpipe_tex_transfer_destroy; - screen->transfer_map = softpipe_transfer_map; - screen->transfer_unmap = softpipe_transfer_unmap; - screen->video_surface_create = softpipe_video_surface_create; screen->video_surface_destroy = softpipe_video_surface_destroy; } -/** - * Return pipe_buffer handle and stride for given texture object. - * XXX used for??? - */ -boolean -softpipe_get_texture_buffer( struct pipe_texture *texture, - struct pipe_buffer **buf, - unsigned *stride ) -{ - struct softpipe_texture *tex = (struct softpipe_texture *) texture; - - if (!tex) - return FALSE; - - pipe_buffer_reference(buf, tex->buffer); - if (stride) - *stride = tex->stride[0]; - - return TRUE; -} diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 2ef64e1e7c3..c0e6ba8a869 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -33,6 +33,10 @@ #include "pipe/p_video_state.h" +#define SP_MAX_TEXTURE_2D_LEVELS 13 /* 4K x 4K */ +#define SP_MAX_TEXTURE_3D_LEVELS 9 /* 512 x 512 x 512 */ + + struct pipe_context; struct pipe_screen; struct softpipe_context; @@ -42,12 +46,19 @@ struct softpipe_texture { struct pipe_texture base; - unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS]; - unsigned stride[PIPE_MAX_TEXTURE_LEVELS]; + unsigned long level_offset[SP_MAX_TEXTURE_2D_LEVELS]; + unsigned stride[SP_MAX_TEXTURE_2D_LEVELS]; - /* The data is held here: + /** + * Display target, for textures with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET + * usage. */ - struct pipe_buffer *buffer; + struct sw_displaytarget *dt; + + /** + * Malloc'ed data for regular textures, or a mapping to dt above. + */ + void *data; /* True if texture images are power-of-two in all dimensions: */ @@ -96,5 +107,8 @@ softpipe_video_surface(struct pipe_video_surface *pvs) extern void softpipe_init_screen_texture_funcs(struct pipe_screen *screen); +void +softpipe_init_texture_funcs(struct pipe_context *pipe); + #endif /* SP_TEXTURE */ diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index aedfdf1b469..1c3c2667d73 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -79,20 +79,20 @@ clear_clear_flag(uint *bitvec, union tile_address addr) struct softpipe_tile_cache * -sp_create_tile_cache( struct pipe_screen *screen ) +sp_create_tile_cache( struct pipe_context *pipe ) { struct softpipe_tile_cache *tc; uint pos; int maxLevels, maxTexSize; /* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */ - maxLevels = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); + maxLevels = pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); maxTexSize = 1 << (maxLevels - 1); assert(MAX_WIDTH >= maxTexSize); tc = CALLOC_STRUCT( softpipe_tile_cache ); if (tc) { - tc->screen = screen; + tc->pipe = pipe; for (pos = 0; pos < NUM_ENTRIES; pos++) { tc->entries[pos].addr.bits.invalid = 1; } @@ -115,15 +115,13 @@ sp_create_tile_cache( struct pipe_screen *screen ) void sp_destroy_tile_cache(struct softpipe_tile_cache *tc) { - struct pipe_screen *screen; uint pos; for (pos = 0; pos < NUM_ENTRIES; pos++) { /*assert(tc->entries[pos].x < 0);*/ } if (tc->transfer) { - screen = tc->transfer->texture->screen; - screen->tex_transfer_destroy(tc->transfer); + tc->pipe->tex_transfer_destroy(tc->pipe, tc->transfer); } FREE( tc ); @@ -137,27 +135,25 @@ void sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { - if (tc->transfer) { - struct pipe_screen *screen = tc->transfer->texture->screen; + struct pipe_context *pipe = tc->pipe; + if (tc->transfer) { if (ps == tc->surface) return; if (tc->transfer_map) { - screen->transfer_unmap(screen, tc->transfer); + pipe->transfer_unmap(pipe, tc->transfer); tc->transfer_map = NULL; } - screen->tex_transfer_destroy(tc->transfer); + pipe->tex_transfer_destroy(pipe, tc->transfer); tc->transfer = NULL; } tc->surface = ps; if (ps) { - struct pipe_screen *screen = ps->texture->screen; - - tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face, + tc->transfer = pipe->get_tex_transfer(pipe, ps->texture, ps->face, ps->level, ps->zslice, PIPE_TRANSFER_READ_WRITE, 0, 0, ps->width, ps->height); @@ -187,7 +183,7 @@ void sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc) { if (tc->transfer && !tc->transfer_map) - tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer); + tc->transfer_map = tc->pipe->transfer_map(tc->pipe, tc->transfer); } @@ -195,7 +191,7 @@ void sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc) { if (tc->transfer_map) { - tc->screen->transfer_unmap(tc->screen, tc->transfer); + tc->pipe->transfer_unmap(tc->pipe, tc->transfer); tc->transfer_map = NULL; } } @@ -295,7 +291,8 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) union tile_address addr = tile_address(x, y); if (is_clear_flag_set(tc->clear_flags, addr)) { - pipe_put_tile_raw(pt, + pipe_put_tile_raw(tc->pipe, + pt, x, y, TILE_SIZE, TILE_SIZE, tc->tile.data.color32, 0/*STRIDE*/); @@ -329,14 +326,14 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) struct softpipe_cached_tile *tile = tc->entries + pos; if (!tile->addr.bits.invalid) { if (tc->depth_stencil) { - pipe_put_tile_raw(pt, + pipe_put_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_put_tile_rgba(pt, + pipe_put_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -379,14 +376,14 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, if (tile->addr.bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { - pipe_put_tile_raw(pt, + pipe_put_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_put_tile_rgba(pt, + pipe_put_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, @@ -409,14 +406,14 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, else { /* get new tile data from transfer */ if (tc->depth_stencil) { - pipe_get_tile_raw(pt, + pipe_get_tile_raw(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { - pipe_get_tile_rgba(pt, + pipe_get_tile_rgba(tc->pipe, pt, tile->addr.bits.x * TILE_SIZE, tile->addr.bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index a12092702a6..753d8c0daac 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -80,7 +80,7 @@ struct softpipe_cached_tile struct softpipe_tile_cache { - struct pipe_screen *screen; + struct pipe_context *pipe; struct pipe_surface *surface; /**< the surface we're caching */ struct pipe_transfer *transfer; void *transfer_map; @@ -98,7 +98,7 @@ struct softpipe_tile_cache extern struct softpipe_tile_cache * -sp_create_tile_cache( struct pipe_screen *screen ); +sp_create_tile_cache( struct pipe_context *pipe ); extern void sp_destroy_tile_cache(struct softpipe_tile_cache *tc); diff --git a/src/gallium/drivers/softpipe/sp_winsys.c b/src/gallium/drivers/softpipe/sp_winsys.c deleted file mode 100644 index 0a6245ed2cd..00000000000 --- a/src/gallium/drivers/softpipe/sp_winsys.c +++ /dev/null @@ -1,245 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA - * 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 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 - * THE COPYRIGHT HOLDERS, AUTHORS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ - -/** - * @file - * Malloc softpipe winsys. Uses malloc for all memory allocations. - * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca - */ - - -#include "util/u_simple_screen.h"/* port to just p_screen */ -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "sp_winsys.h" - - -struct st_softpipe_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; - void *mapped; -}; - - -/** Cast wrapper */ -static INLINE struct st_softpipe_buffer * -st_softpipe_buffer( struct pipe_buffer *buf ) -{ - return (struct st_softpipe_buffer *)buf; -} - - -static void * -st_softpipe_buffer_map(struct pipe_winsys *winsys, - struct pipe_buffer *buf, - unsigned flags) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = st_softpipe_buf->data; - return st_softpipe_buf->mapped; -} - - -static void -st_softpipe_buffer_unmap(struct pipe_winsys *winsys, - struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); - st_softpipe_buf->mapped = NULL; -} - - -static void -st_softpipe_buffer_destroy(struct pipe_buffer *buf) -{ - struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); - - if (oldBuf->data) { - if (!oldBuf->userBuffer) - align_free(oldBuf->data); - - oldBuf->data = NULL; - } - - FREE(oldBuf); -} - - -static void -st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, - struct pipe_surface *surf, - void *context_private) -{ -} - - - -static const char * -st_softpipe_get_name(struct pipe_winsys *winsys) -{ - return "softpipe"; -} - - -static struct pipe_buffer * -st_softpipe_buffer_create(struct pipe_winsys *winsys, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.alignment = alignment; - 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 * -st_softpipe_user_buffer_create(struct pipe_winsys *winsys, - void *ptr, - unsigned bytes) -{ - struct st_softpipe_buffer *buffer; - - buffer = CALLOC_STRUCT(st_softpipe_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -static struct pipe_buffer * -st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -st_softpipe_fence_reference(struct pipe_winsys *winsys, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -st_softpipe_fence_signalled(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -st_softpipe_fence_finish(struct pipe_winsys *winsys, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static void -st_softpipe_destroy(struct pipe_winsys *winsys) -{ - FREE(winsys); -} - - -struct pipe_screen * -softpipe_create_screen_malloc(void) -{ - static struct pipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(pipe_winsys); - if(!winsys) - return NULL; - - winsys->destroy = st_softpipe_destroy; - - winsys->buffer_create = st_softpipe_buffer_create; - winsys->user_buffer_create = st_softpipe_user_buffer_create; - winsys->buffer_map = st_softpipe_buffer_map; - winsys->buffer_unmap = st_softpipe_buffer_unmap; - winsys->buffer_destroy = st_softpipe_buffer_destroy; - - winsys->surface_buffer_create = st_softpipe_surface_buffer_create; - - winsys->fence_reference = st_softpipe_fence_reference; - winsys->fence_signalled = st_softpipe_fence_signalled; - winsys->fence_finish = st_softpipe_fence_finish; - - winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; - winsys->get_name = st_softpipe_get_name; - - screen = softpipe_create_screen(winsys); - if(!screen) - st_softpipe_destroy(winsys); - - return screen; -} diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 03302e2a6ec..791d30edc0e 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -169,6 +169,11 @@ struct svga_sampler_state { unsigned view_max_lod; }; +struct svga_velems_state { + unsigned count; + struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; +}; + /* Use to calculate differences between state emitted to hardware and * current driver-calculated state. */ @@ -178,13 +183,13 @@ struct svga_state const struct svga_depth_stencil_state *depth; const struct svga_rasterizer_state *rast; const struct svga_sampler_state *sampler[PIPE_MAX_SAMPLERS]; + const struct svga_velems_state *velems; struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; /* or texture ID's? */ struct svga_fragment_shader *fs; struct svga_vertex_shader *vs; struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; struct pipe_buffer *cb[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; @@ -204,7 +209,6 @@ struct svga_state unsigned num_samplers; unsigned num_textures; - unsigned num_vertex_elements; unsigned num_vertex_buffers; unsigned reduced_prim; diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c index acba2b8f9da..1a8ef296cac 100644 --- a/src/gallium/drivers/svga/svga_pipe_sampler.c +++ b/src/gallium/drivers/svga/svga_pipe_sampler.c @@ -155,7 +155,7 @@ static void svga_bind_sampler_states(struct pipe_context *pipe, /* Check for no-op */ if (num == svga->curr.num_samplers && !memcmp(svga->curr.sampler, sampler, num * sizeof(void *))) { - debug_printf("sampler noop\n"); + if (0) debug_printf("sampler noop\n"); return; } diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 836b8441da2..1715a47fc62 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -26,6 +26,7 @@ #include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" +#include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "svga_screen.h" @@ -64,20 +65,37 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe, svga->dirty |= SVGA_NEW_VBUFFER; } -static void svga_set_vertex_elements(struct pipe_context *pipe, - unsigned count, - const struct pipe_vertex_element *elements) + +static void * +svga_create_vertex_elements_state(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *attribs) { - struct svga_context *svga = svga_context(pipe); - unsigned i; + struct svga_velems_state *velems; + assert(count <= PIPE_MAX_ATTRIBS); + velems = (struct svga_velems_state *) MALLOC(sizeof(struct svga_velems_state)); + if (velems) { + velems->count = count; + memcpy(velems->velem, attribs, sizeof(*attribs) * count); + } + return velems; +} - for (i = 0; i < count; i++) - svga->curr.ve[i] = elements[i]; +static void svga_bind_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + struct svga_context *svga = svga_context(pipe); + struct svga_velems_state *svga_velems = (struct svga_velems_state *) velems; - svga->curr.num_vertex_elements = count; + svga->curr.velems = svga_velems; svga->dirty |= SVGA_NEW_VELEMENT; } +static void svga_delete_vertex_elements_state(struct pipe_context *pipe, + void *velems) +{ + FREE(velems); +} void svga_cleanup_vertex_state( struct svga_context *svga ) { @@ -91,7 +109,9 @@ void svga_cleanup_vertex_state( struct svga_context *svga ) void svga_init_vertex_functions( struct svga_context *svga ) { svga->pipe.set_vertex_buffers = svga_set_vertex_buffers; - svga->pipe.set_vertex_elements = svga_set_vertex_elements; + svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state; + svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state; + svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state; } diff --git a/src/gallium/drivers/svga/svga_screen_texture.c b/src/gallium/drivers/svga/svga_screen_texture.c index e9792e063e0..107e4a39620 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.c +++ b/src/gallium/drivers/svga/svga_screen_texture.c @@ -315,7 +315,11 @@ svga_texture_create(struct pipe_screen *screen, tex->key.cachable = 0; } - if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) { + if(templat->tex_usage & PIPE_TEXTURE_USAGE_SHARED) { + tex->key.cachable = 0; + } + + if(templat->tex_usage & PIPE_TEXTURE_USAGE_SCANOUT) { tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT; tex->key.cachable = 0; } @@ -355,80 +359,18 @@ error1: } -static struct pipe_texture * -svga_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) -{ - struct svga_texture *tex; - struct svga_buffer *sbuf = svga_buffer(buffer); - struct svga_winsys_screen *sws = svga_winsys_screen(screen); - assert(screen); - - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; - } - - /** - * We currently can't do texture blanket on - * SVGA3D_BUFFER. Need to blit to a temporary surface? - */ - assert(sbuf->handle); - if (!sbuf->handle) - return NULL; - if (svga_translate_format(base->format) != sbuf->key.format) { - unsigned f1 = svga_translate_format(base->format); - unsigned f2 = sbuf->key.format; - /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */ - if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) || - (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) || - (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) ) ) { - debug_printf("%s wrong format %u != %u\n", __FUNCTION__, f1, f2); - return NULL; - } - } - - tex = CALLOC_STRUCT(svga_texture); - if (!tex) - return NULL; - - tex->base = *base; - - - if (sbuf->key.format == 1) - tex->base.format = PIPE_FORMAT_B8G8R8X8_UNORM; - else if (sbuf->key.format == 2) - tex->base.format = PIPE_FORMAT_B8G8R8A8_UNORM; - - pipe_reference_init(&tex->base.reference, 1); - tex->base.screen = screen; - - SVGA_DBG(DEBUG_DMA, "blanket sid %p\n", sbuf->handle); - - /* We don't own this storage, so don't try to cache it. - */ - assert(sbuf->key.cachable == 0); - tex->key.cachable = 0; - sws->surface_reference(sws, &tex->handle, sbuf->handle); - - return &tex->base; -} - - -struct pipe_texture * -svga_screen_texture_wrap_surface(struct pipe_screen *screen, - struct pipe_texture *base, - enum SVGA3dSurfaceFormat format, - struct svga_winsys_surface *srf) +static struct pipe_texture * +svga_screen_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *base, + struct winsys_handle *whandle) { + struct svga_winsys_screen *sws = svga_winsys_screen(screen); + struct svga_winsys_surface *srf; struct svga_texture *tex; + enum SVGA3dSurfaceFormat format = 0; assert(screen); /* Only supports one type */ @@ -438,6 +380,8 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen, return NULL; } + srf = sws->surface_from_handle(sws, whandle, &format); + if (!srf) return NULL; @@ -478,6 +422,22 @@ svga_screen_texture_wrap_surface(struct pipe_screen *screen, } +static boolean +svga_screen_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *texture, + struct winsys_handle *whandle) +{ + struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen); + unsigned stride; + + assert(svga_texture(texture)->key.cachable == 0); + svga_texture(texture)->key.cachable = 0; + stride = util_format_get_nblocksx(texture->format, texture->width0) * + util_format_get_blocksize(texture->format); + return sws->surface_get_handle(sws, svga_texture(texture)->handle, stride, whandle); +} + + static void svga_texture_destroy(struct pipe_texture *pt) { @@ -823,15 +783,17 @@ svga_surface_needs_propagation(struct pipe_surface *surf) return s->dirty && s->handle != tex->handle; } - +/* XXX: Still implementing this as if it was a screen function, but + * can now modify it to queue transfers on the context. + */ static struct pipe_transfer * -svga_get_tex_transfer(struct pipe_screen *screen, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, unsigned x, unsigned y, - unsigned w, unsigned h) +svga_get_tex_transfer(struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, unsigned x, unsigned y, + unsigned w, unsigned h) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st; unsigned nblocksx = util_format_get_nblocksx(texture->format, w); @@ -899,11 +861,14 @@ no_hwbuf: } +/* XXX: Still implementing this as if it was a screen function, but + * can now modify it to queue transfers on the context. + */ static void * -svga_transfer_map( struct pipe_screen *screen, +svga_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); @@ -917,11 +882,14 @@ svga_transfer_map( struct pipe_screen *screen, } +/* XXX: Still implementing this as if it was a screen function, but + * can now modify it to queue transfers on the context. + */ static void -svga_transfer_unmap(struct pipe_screen *screen, +svga_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct svga_screen *ss = svga_screen(screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); @@ -931,10 +899,11 @@ svga_transfer_unmap(struct pipe_screen *screen, static void -svga_tex_transfer_destroy(struct pipe_transfer *transfer) +svga_tex_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) { struct svga_texture *tex = svga_texture(transfer->texture); - struct svga_screen *ss = svga_screen(transfer->texture->screen); + struct svga_screen *ss = svga_screen(pipe->screen); struct svga_winsys_screen *sws = ss->sws; struct svga_transfer *st = svga_transfer(transfer); @@ -951,18 +920,26 @@ svga_tex_transfer_destroy(struct pipe_transfer *transfer) FREE(st); } + +void +svga_init_texture_functions(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = svga_get_tex_transfer; + pipe->transfer_map = svga_transfer_map; + pipe->transfer_unmap = svga_transfer_unmap; + pipe->tex_transfer_destroy = svga_tex_transfer_destroy; +} + + void svga_screen_init_texture_functions(struct pipe_screen *screen) { screen->texture_create = svga_texture_create; + screen->texture_from_handle = svga_screen_texture_from_handle; + screen->texture_get_handle = svga_screen_texture_get_handle; screen->texture_destroy = svga_texture_destroy; screen->get_tex_surface = svga_get_tex_surface; screen->tex_surface_destroy = svga_tex_surface_destroy; - screen->texture_blanket = svga_texture_blanket; - screen->get_tex_transfer = svga_get_tex_transfer; - screen->transfer_map = svga_transfer_map; - screen->transfer_unmap = svga_transfer_unmap; - screen->tex_transfer_destroy = svga_tex_transfer_destroy; } /*********************************************************************** @@ -1120,33 +1097,3 @@ svga_destroy_sampler_view_priv(struct svga_sampler_view *v) pipe_texture_reference(&v->texture, NULL); FREE(v); } - -boolean -svga_screen_buffer_from_texture(struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride) -{ - struct svga_texture *stex = svga_texture(texture); - - *buffer = svga_screen_buffer_wrap_surface - (texture->screen, - svga_translate_format(texture->format), - stex->handle); - - *stride = util_format_get_stride(texture->format, texture->width0); - - return *buffer != NULL; -} - - -struct svga_winsys_surface * -svga_screen_texture_get_winsys_surface(struct pipe_texture *texture) -{ - struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen); - struct svga_winsys_surface *vsurf = NULL; - - assert(svga_texture(texture)->key.cachable == 0); - svga_texture(texture)->key.cachable = 0; - sws->surface_reference(sws, &vsurf, svga_texture(texture)->handle); - return vsurf; -} diff --git a/src/gallium/drivers/svga/svga_screen_texture.h b/src/gallium/drivers/svga/svga_screen_texture.h index 24c1f78ca55..96d035b12d8 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.h +++ b/src/gallium/drivers/svga/svga_screen_texture.h @@ -78,7 +78,7 @@ struct svga_texture { struct pipe_texture base; - boolean defined[6][PIPE_MAX_TEXTURE_LEVELS]; + boolean defined[6][SVGA_MAX_TEXTURE_LEVELS]; struct svga_sampler_view *cached_view; @@ -186,6 +186,9 @@ svga_surface_needs_propagation(struct pipe_surface *surf); extern void svga_screen_init_texture_functions(struct pipe_screen *screen); +void +svga_init_texture_functions(struct pipe_context *pipe); + enum SVGA3dSurfaceFormat svga_translate_format(enum pipe_format format); diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c index d774e3e504d..dfaab53aef4 100644 --- a/src/gallium/drivers/svga/svga_state_need_swtnl.c +++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c @@ -76,8 +76,13 @@ static int update_need_swvfetch( struct svga_context *svga, unsigned i; boolean need_swvfetch = FALSE; - for (i = 0; i < svga->curr.num_vertex_elements; i++) { - svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.ve[i].src_format); + if (!svga->curr.velems) { + /* No vertex elements bound. */ + return 0; + } + + for (i = 0; i < svga->curr.velems->count; i++) { + svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.velems->velem[i].src_format); if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) { need_swvfetch = TRUE; break; diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index 107cc403b4d..b7195d246bc 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -191,15 +191,24 @@ static int emit_rss( struct svga_context *svga, EMIT_RS( svga, svga->curr.stencil_ref.ref_value[0], STENCILREF, fail ); } - if (dirty & SVGA_NEW_RAST) + if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE)) { const struct svga_rasterizer_state *curr = svga->curr.rast; + unsigned cullmode = curr->cullmode; /* Shademode: still need to rearrange index list to move * flat-shading PV first vertex. */ EMIT_RS( svga, curr->shademode, SHADEMODE, fail ); - EMIT_RS( svga, curr->cullmode, CULLMODE, fail ); + + /* Don't do culling while the software pipeline is active. It + * does it for us, and additionally introduces potentially + * back-facing triangles. + */ + if (svga->state.sw.need_pipeline) + cullmode = SVGA3D_FACE_NONE; + + EMIT_RS( svga, cullmode, CULLMODE, fail ); EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail ); EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail ); EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail ); diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c index ded903170b5..f531e223048 100644 --- a/src/gallium/drivers/svga/svga_state_vdecl.c +++ b/src/gallium/drivers/svga/svga_state_vdecl.c @@ -95,17 +95,17 @@ upload_user_buffers( struct svga_context *svga ) static int emit_hw_vs_vdecl( struct svga_context *svga, unsigned dirty ) { - const struct pipe_vertex_element *ve = svga->curr.ve; + const struct pipe_vertex_element *ve = svga->curr.velems->velem; SVGA3dVertexDecl decl; unsigned i; - assert(svga->curr.num_vertex_elements >= + assert(svga->curr.velems->count >= svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]); svga_hwtnl_reset_vdecl( svga->hwtnl, - svga->curr.num_vertex_elements ); + svga->curr.velems->count ); - for (i = 0; i < svga->curr.num_vertex_elements; i++) { + for (i = 0; i < svga->curr.velems->count; i++) { const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index]; unsigned usage, index; diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c index d7999fe53d2..781f7bf5339 100644 --- a/src/gallium/drivers/svga/svga_state_vs.c +++ b/src/gallium/drivers/svga/svga_state_vs.c @@ -186,8 +186,8 @@ static int update_zero_stride( struct svga_context *svga, svga->curr.zero_stride_vertex_elements = 0; svga->curr.num_zero_stride_vertex_elements = 0; - for (i = 0; i < svga->curr.num_vertex_elements; i++) { - const struct pipe_vertex_element *vel = &svga->curr.ve[i]; + for (i = 0; i < svga->curr.velems->count; i++) { + const struct pipe_vertex_element *vel = &svga->curr.velems->velem[i]; const struct pipe_vertex_buffer *vbuffer = &svga->curr.vb[ vel->vertex_buffer_index]; if (vbuffer->stride == 0) { diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index 35f36a828fd..246d34e649e 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -99,8 +99,8 @@ static int update_swtnl_draw( struct svga_context *svga, if (dirty & SVGA_NEW_VELEMENT) draw_set_vertex_elements(svga->swtnl.draw, - svga->curr.num_vertex_elements, - svga->curr.ve ); + svga->curr.velems->count, + svga->curr.velems->velem ); if (dirty & SVGA_NEW_CLIP) draw_set_clip_state(svga->swtnl.draw, diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h index b4e3af0eafc..d4bb176f9a8 100644 --- a/src/gallium/drivers/svga/svga_winsys.h +++ b/src/gallium/drivers/svga/svga_winsys.h @@ -51,6 +51,7 @@ struct pipe_context; struct pipe_fence_handle; struct pipe_texture; struct svga_region; +struct winsys_handle; #define SVGA_BUFFER_USAGE_PINNED (PIPE_BUFFER_USAGE_CUSTOM << 0) @@ -187,6 +188,25 @@ struct svga_winsys_screen uint32 numMipLevels); /** + * Creates a surface from a winsys handle. + * Used to implement pipe_screen::texture_from_handle. + */ + struct svga_winsys_surface * + (*surface_from_handle)(struct svga_winsys_screen *sws, + struct winsys_handle *whandle, + SVGA3dSurfaceFormat *format); + + /** + * Get a winsys_handle from a surface. + * Used to implement pipe_screen::texture_get_handle. + */ + boolean + (*surface_get_handle)(struct svga_winsys_screen *sws, + struct svga_winsys_surface *surface, + unsigned stride, + struct winsys_handle *whandle); + + /** * Whether this surface is sitting in a validate list */ boolean @@ -284,19 +304,6 @@ svga_screen_buffer_wrap_surface(struct pipe_screen *screen, struct svga_winsys_surface *srf); struct svga_winsys_surface * -svga_screen_texture_get_winsys_surface(struct pipe_texture *texture); -struct svga_winsys_surface * svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer); -boolean -svga_screen_buffer_from_texture(struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride); - -struct pipe_texture * -svga_screen_texture_wrap_surface(struct pipe_screen *screen, - struct pipe_texture *base, - enum SVGA3dSurfaceFormat format, - struct svga_winsys_surface *srf); - #endif /* SVGA_WINSYS_H_ */ diff --git a/src/gallium/drivers/svga/svgadump/svga_shader_dump.c b/src/gallium/drivers/svga/svgadump/svga_shader_dump.c index 705ca29e8f5..4ee1bf2c353 100644 --- a/src/gallium/drivers/svga/svgadump/svga_shader_dump.c +++ b/src/gallium/drivers/svga/svgadump/svga_shader_dump.c @@ -360,7 +360,9 @@ dump_dstreg(struct sh_dstreg dstreg, union { struct sh_reg reg; struct sh_dstreg dstreg; - } u = { { 0 } }; + } u; + + memset(&u, 0, sizeof(u)); assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier ); diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index df40fbade6c..b7e6bbac68e 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -27,7 +27,9 @@ #include "util/u_memory.h" #include "util/u_simple_list.h" +#include "util/u_format.h" +#include "pipe/p_format.h" #include "pipe/p_screen.h" #include "tr_dump.h" @@ -773,6 +775,70 @@ trace_context_delete_vs_state(struct pipe_context *_pipe, } +static INLINE void * +trace_context_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_vertex_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_elements); + + trace_dump_arg_begin("elements"); + trace_dump_struct_array(vertex_element, elements, num_elements); + trace_dump_arg_end(); + + result = pipe->create_vertex_elements_state(pipe, num_elements, elements); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_bind_vertex_elements_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "bind_vertex_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->bind_vertex_elements_state(pipe, state); + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_delete_vertex_elements_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_verte_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_vertex_elements_state(pipe, state); + + trace_dump_call_end(); +} + + static INLINE void trace_context_set_blend_color(struct pipe_context *_pipe, const struct pipe_blend_color *state) @@ -1048,29 +1114,6 @@ trace_context_set_vertex_buffers(struct pipe_context *_pipe, static INLINE void -trace_context_set_vertex_elements(struct pipe_context *_pipe, - unsigned num_elements, - const struct pipe_vertex_element *elements) -{ - struct trace_context *tr_ctx = trace_context(_pipe); - struct pipe_context *pipe = tr_ctx->pipe; - - trace_dump_call_begin("pipe_context", "set_vertex_elements"); - - trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, num_elements); - - trace_dump_arg_begin("elements"); - trace_dump_struct_array(vertex_element, elements, num_elements); - trace_dump_arg_end(); - - pipe->set_vertex_elements(pipe, num_elements, elements); - - trace_dump_call_end(); -} - - -static INLINE void trace_context_surface_copy(struct pipe_context *_pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, @@ -1242,6 +1285,136 @@ trace_is_buffer_referenced( struct pipe_context *_pipe, return referenced; } + +/******************************************************************** + * transfer + */ + + +static struct pipe_transfer * +trace_context_get_tex_transfer(struct pipe_context *_context, + struct pipe_texture *_texture, + unsigned face, unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_context *context = tr_context->pipe; + struct pipe_texture *texture = tr_tex->texture; + struct pipe_transfer *result = NULL; + + assert(texture->screen == context->screen); + + trace_dump_call_begin("pipe_context", "get_tex_transfer"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, texture); + trace_dump_arg(uint, face); + trace_dump_arg(uint, level); + trace_dump_arg(uint, zslice); + trace_dump_arg(uint, usage); + + trace_dump_arg(uint, x); + trace_dump_arg(uint, y); + trace_dump_arg(uint, w); + trace_dump_arg(uint, h); + + result = context->get_tex_transfer(context, texture, face, level, zslice, usage, + x, y, w, h); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + if (result) + result = trace_transfer_create(tr_context, tr_tex, result); + + return result; +} + + +static void +trace_context_tex_transfer_destroy(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + + trace_dump_call_begin("pipe_context", "tex_transfer_destroy"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, transfer); + + trace_dump_call_end(); + + trace_transfer_destroy(tr_context, tr_trans); +} + + +static void * +trace_context_transfer_map(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + void *map; + + map = context->transfer_map(context, transfer); + if(map) { + if(transfer->usage & PIPE_TRANSFER_WRITE) { + assert(!tr_trans->map); + tr_trans->map = map; + } + } + + return map; +} + + +static void +trace_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_ctx = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_ctx->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + + if(tr_trans->map) { + size_t size = util_format_get_nblocksy(transfer->texture->format, transfer->height) * transfer->stride; + + trace_dump_call_begin("pipe_context", "transfer_write"); + + trace_dump_arg(ptr, context); + + trace_dump_arg(ptr, transfer); + + trace_dump_arg_begin("stride"); + trace_dump_uint(transfer->stride); + trace_dump_arg_end(); + + trace_dump_arg_begin("data"); + trace_dump_bytes(tr_trans->map, size); + trace_dump_arg_end(); + + trace_dump_arg_begin("size"); + trace_dump_uint(size); + trace_dump_arg_end(); + + trace_dump_call_end(); + + tr_trans->map = NULL; + } + + context->transfer_unmap(context, transfer); +} + static const struct debug_named_value rbug_blocker_flags[] = { {"before", 1}, {"after", 2}, @@ -1303,6 +1476,9 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.create_vs_state = trace_context_create_vs_state; tr_ctx->base.bind_vs_state = trace_context_bind_vs_state; tr_ctx->base.delete_vs_state = trace_context_delete_vs_state; + tr_ctx->base.create_vertex_elements_state = trace_context_create_vertex_elements_state; + tr_ctx->base.bind_vertex_elements_state = trace_context_bind_vertex_elements_state; + tr_ctx->base.delete_vertex_elements_state = trace_context_delete_vertex_elements_state; tr_ctx->base.set_blend_color = trace_context_set_blend_color; tr_ctx->base.set_stencil_ref = trace_context_set_stencil_ref; tr_ctx->base.set_clip_state = trace_context_set_clip_state; @@ -1314,7 +1490,6 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.set_fragment_sampler_textures = trace_context_set_fragment_sampler_textures; tr_ctx->base.set_vertex_sampler_textures = trace_context_set_vertex_sampler_textures; tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers; - tr_ctx->base.set_vertex_elements = trace_context_set_vertex_elements; if (pipe->surface_copy) tr_ctx->base.surface_copy = trace_context_surface_copy; if (pipe->surface_fill) @@ -1324,6 +1499,11 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.is_texture_referenced = trace_is_texture_referenced; tr_ctx->base.is_buffer_referenced = trace_is_buffer_referenced; + tr_ctx->base.get_tex_transfer = trace_context_get_tex_transfer; + tr_ctx->base.tex_transfer_destroy = trace_context_tex_transfer_destroy; + tr_ctx->base.transfer_map = trace_context_transfer_map; + tr_ctx->base.transfer_unmap = trace_context_transfer_unmap; + tr_ctx->pipe = pipe; trace_screen_add_to_list(tr_scr, contexts, tr_ctx); diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 2b4915003e2..906b3262e4b 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -33,6 +33,7 @@ #include "tr_context.h" #include "tr_buffer.h" #include "tr_texture.h" +#include "tr_public.h" struct trace_drm_api { @@ -62,69 +63,8 @@ trace_drm_create_screen(struct drm_api *_api, int fd, screen = api->create_screen(api, fd, arg); - return trace_screen_create(screen); -} - - -static struct pipe_texture * -trace_drm_texture_from_shared_handle(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *templ, - const char *name, - unsigned stride, - unsigned handle) -{ - struct trace_screen *tr_screen = trace_screen(_screen); - struct trace_drm_api *tr_api = trace_drm_api(_api); - struct pipe_screen *screen = tr_screen->screen; - struct drm_api *api = tr_api->api; - struct pipe_texture *result; - - /* TODO trace call */ - - result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle); - - result = trace_texture_create(trace_screen(_screen), result); - - return result; -} - -static boolean -trace_drm_shared_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct trace_screen *tr_screen = trace_screen(_screen); - struct trace_texture *tr_texture = trace_texture(_texture); - struct trace_drm_api *tr_api = trace_drm_api(_api); - struct pipe_screen *screen = tr_screen->screen; - struct pipe_texture *texture = tr_texture->texture; - struct drm_api *api = tr_api->api; - - /* TODO trace call */ - - return api->shared_handle_from_texture(api, screen, texture, stride, handle); -} -static boolean -trace_drm_local_handle_from_texture(struct drm_api *_api, - struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned *stride, - unsigned *handle) -{ - struct trace_screen *tr_screen = trace_screen(_screen); - struct trace_texture *tr_texture = trace_texture(_texture); - struct trace_drm_api *tr_api = trace_drm_api(_api); - struct pipe_screen *screen = tr_screen->screen; - struct pipe_texture *texture = tr_texture->texture; - struct drm_api *api = tr_api->api; - - /* TODO trace call */ - - return api->local_handle_from_texture(api, screen, texture, stride, handle); + return trace_screen_create(screen); } static void @@ -158,9 +98,6 @@ trace_drm_create(struct drm_api *api) tr_api->base.name = api->name; tr_api->base.driver_name = api->driver_name; tr_api->base.create_screen = trace_drm_create_screen; - tr_api->base.texture_from_shared_handle = trace_drm_texture_from_shared_handle; - tr_api->base.shared_handle_from_texture = trace_drm_shared_handle_from_texture; - tr_api->base.local_handle_from_texture = trace_drm_local_handle_from_texture; tr_api->base.destroy = trace_drm_destroy; tr_api->api = api; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index f97d963dba6..f82dd01c697 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -479,7 +479,6 @@ void trace_dump_vertex_element(const struct pipe_vertex_element *state) trace_dump_member(uint, state, src_offset); trace_dump_member(uint, state, vertex_buffer_index); - trace_dump_member(uint, state, nr_components); trace_dump_member(format, state, src_format); diff --git a/src/gallium/drivers/trace/tr_public.h b/src/gallium/drivers/trace/tr_public.h new file mode 100644 index 00000000000..62e217097d0 --- /dev/null +++ b/src/gallium/drivers/trace/tr_public.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2010 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +#ifndef TR_PUBLIC_H +#define TR_PUBLIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +trace_screen_create(struct pipe_screen *screen); + +#ifdef __cplusplus +} +#endif + +#endif /* TR_PUBLIC_H */ diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c index a43adac6940..f4f17566fd3 100644 --- a/src/gallium/drivers/trace/tr_rbug.c +++ b/src/gallium/drivers/trace/tr_rbug.c @@ -219,7 +219,7 @@ trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, struct trace_texture *tr_tex = NULL; struct tr_list *ptr; - struct pipe_screen *screen = tr_scr->screen; + struct pipe_context *context = tr_scr->private_context; struct pipe_texture *tex; struct pipe_transfer *t; @@ -239,12 +239,12 @@ trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, } tex = tr_tex->texture; - t = screen->get_tex_transfer(tr_scr->screen, tex, - gptr->face, gptr->level, gptr->zslice, - PIPE_TRANSFER_READ, - gptr->x, gptr->y, gptr->w, gptr->h); + t = context->get_tex_transfer(context, tex, + gptr->face, gptr->level, gptr->zslice, + PIPE_TRANSFER_READ, + gptr->x, gptr->y, gptr->w, gptr->h); - map = screen->transfer_map(screen, t); + map = context->transfer_map(context, t); rbug_send_texture_read_reply(tr_rbug->con, serial, t->texture->format, @@ -256,8 +256,8 @@ trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, t->stride, NULL); - screen->transfer_unmap(screen, t); - screen->tex_transfer_destroy(t); + context->transfer_unmap(context, t); + context->tex_transfer_destroy(context, t); pipe_mutex_unlock(tr_scr->list_mutex); diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index 388d83eb5c2..25990bdac7f 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -35,6 +35,7 @@ #include "tr_texture.h" #include "tr_context.h" #include "tr_screen.h" +#include "tr_public.h" #include "util/u_inlines.h" #include "pipe/p_format.h" @@ -236,39 +237,41 @@ trace_screen_texture_create(struct pipe_screen *_screen, return result; } - static struct pipe_texture * -trace_screen_texture_blanket(struct pipe_screen *_screen, - const struct pipe_texture *templat, - const unsigned *ppitch, - struct pipe_buffer *_buffer) +trace_screen_texture_from_handle(struct pipe_screen *_screen, + const struct pipe_texture *templ, + struct winsys_handle *handle) { - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_buffer *tr_buf = trace_buffer(_buffer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_buffer *buffer = tr_buf->buffer; - unsigned pitch = *ppitch; + struct trace_screen *tr_screen = trace_screen(_screen); + struct pipe_screen *screen = tr_screen->screen; struct pipe_texture *result; - trace_dump_call_begin("pipe_screen", "texture_blanket"); + /* TODO trace call */ - trace_dump_arg(ptr, screen); - trace_dump_arg(template, templat); - trace_dump_arg(uint, pitch); - trace_dump_arg(ptr, buffer); + result = screen->texture_from_handle(screen, templ, handle); - result = screen->texture_blanket(screen, templat, ppitch, buffer); + result = trace_texture_create(trace_screen(_screen), result); - trace_dump_ret(ptr, result); + return result; +} - trace_dump_call_end(); +static boolean +trace_screen_texture_get_handle(struct pipe_screen *_screen, + struct pipe_texture *_texture, + struct winsys_handle *handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_texture *tr_texture = trace_texture(_texture); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_texture *texture = tr_texture->texture; - result = trace_texture_create(tr_scr, result); + /* TODO trace call */ - return result; + return screen->texture_get_handle(screen, texture, handle); } + static void trace_screen_texture_destroy(struct pipe_texture *_texture) { @@ -350,133 +353,7 @@ trace_screen_tex_surface_destroy(struct pipe_surface *_surface) } -/******************************************************************** - * transfer - */ - - -static struct pipe_transfer * -trace_screen_get_tex_transfer(struct pipe_screen *_screen, - struct pipe_texture *_texture, - unsigned face, unsigned level, - unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_texture *tr_tex = trace_texture(_texture); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_texture *texture = tr_tex->texture; - struct pipe_transfer *result = NULL; - - assert(texture->screen == screen); - - trace_dump_call_begin("pipe_screen", "get_tex_transfer"); - trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, texture); - trace_dump_arg(uint, face); - trace_dump_arg(uint, level); - trace_dump_arg(uint, zslice); - trace_dump_arg(uint, usage); - - trace_dump_arg(uint, x); - trace_dump_arg(uint, y); - trace_dump_arg(uint, w); - trace_dump_arg(uint, h); - - result = screen->get_tex_transfer(screen, texture, face, level, zslice, usage, - x, y, w, h); - - trace_dump_ret(ptr, result); - - trace_dump_call_end(); - - if (result) - result = trace_transfer_create(tr_tex, result); - - return result; -} - - -static void -trace_screen_tex_transfer_destroy(struct pipe_transfer *_transfer) -{ - struct trace_screen *tr_scr = trace_screen(_transfer->texture->screen); - struct trace_transfer *tr_trans = trace_transfer(_transfer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_transfer *transfer = tr_trans->transfer; - - trace_dump_call_begin("pipe_screen", "tex_transfer_destroy"); - - trace_dump_arg(ptr, screen); - trace_dump_arg(ptr, transfer); - - trace_dump_call_end(); - - trace_transfer_destroy(tr_trans); -} - - -static void * -trace_screen_transfer_map(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_transfer *tr_trans = trace_transfer(_transfer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_transfer *transfer = tr_trans->transfer; - void *map; - - map = screen->transfer_map(screen, transfer); - if(map) { - if(transfer->usage & PIPE_TRANSFER_WRITE) { - assert(!tr_trans->map); - tr_trans->map = map; - } - } - - return map; -} - - -static void -trace_screen_transfer_unmap(struct pipe_screen *_screen, - struct pipe_transfer *_transfer) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct trace_transfer *tr_trans = trace_transfer(_transfer); - struct pipe_screen *screen = tr_scr->screen; - struct pipe_transfer *transfer = tr_trans->transfer; - - if(tr_trans->map) { - size_t size = util_format_get_nblocksy(transfer->texture->format, transfer->height) * transfer->stride; - - trace_dump_call_begin("pipe_screen", "transfer_write"); - - trace_dump_arg(ptr, screen); - - trace_dump_arg(ptr, transfer); - - trace_dump_arg_begin("stride"); - trace_dump_uint(transfer->stride); - trace_dump_arg_end(); - - trace_dump_arg_begin("data"); - trace_dump_bytes(tr_trans->map, size); - trace_dump_arg_end(); - - trace_dump_arg_begin("size"); - trace_dump_uint(size); - trace_dump_arg_end(); - - trace_dump_call_end(); - - tr_trans->map = NULL; - } - - screen->transfer_unmap(screen, transfer); -} /******************************************************************** @@ -484,45 +361,7 @@ trace_screen_transfer_unmap(struct pipe_screen *_screen, */ -static struct pipe_buffer * -trace_screen_surface_buffer_create(struct pipe_screen *_screen, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *pstride) -{ - struct trace_screen *tr_scr = trace_screen(_screen); - struct pipe_screen *screen = tr_scr->screen; - unsigned stride; - struct pipe_buffer *result; - - trace_dump_call_begin("pipe_screen", "surface_buffer_create"); - - trace_dump_arg(ptr, screen); - trace_dump_arg(uint, width); - trace_dump_arg(uint, height); - trace_dump_arg(format, format); - trace_dump_arg(uint, usage); - trace_dump_arg(uint, tex_usage); - - result = screen->surface_buffer_create(screen, - width, height, - format, - usage, - tex_usage, - pstride); - - stride = *pstride; - - trace_dump_arg(uint, stride); - - trace_dump_ret(ptr, result); - - trace_dump_call_end(); - return trace_buffer_create(tr_scr, result); -} static struct pipe_buffer * @@ -931,17 +770,13 @@ trace_screen_create(struct pipe_screen *screen) assert(screen->context_create); tr_scr->base.context_create = trace_screen_context_create; tr_scr->base.texture_create = trace_screen_texture_create; - tr_scr->base.texture_blanket = trace_screen_texture_blanket; + tr_scr->base.texture_from_handle = trace_screen_texture_from_handle; + tr_scr->base.texture_get_handle = trace_screen_texture_get_handle; tr_scr->base.texture_destroy = trace_screen_texture_destroy; tr_scr->base.get_tex_surface = trace_screen_get_tex_surface; tr_scr->base.tex_surface_destroy = trace_screen_tex_surface_destroy; - tr_scr->base.get_tex_transfer = trace_screen_get_tex_transfer; - tr_scr->base.tex_transfer_destroy = trace_screen_tex_transfer_destroy; - tr_scr->base.transfer_map = trace_screen_transfer_map; - tr_scr->base.transfer_unmap = trace_screen_transfer_unmap; tr_scr->base.buffer_create = trace_screen_buffer_create; tr_scr->base.user_buffer_create = trace_screen_user_buffer_create; - tr_scr->base.surface_buffer_create = trace_screen_surface_buffer_create; if (screen->buffer_map) tr_scr->base.buffer_map = trace_screen_buffer_map; if (screen->buffer_map_range) @@ -955,7 +790,11 @@ trace_screen_create(struct pipe_screen *screen) tr_scr->base.fence_signalled = trace_screen_fence_signalled; tr_scr->base.fence_finish = trace_screen_fence_finish; tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer; + tr_scr->screen = screen; + tr_scr->private_context = screen->context_create(screen, NULL); + if (tr_scr->private_context == NULL) + goto error3; trace_dump_ret(ptr, screen); trace_dump_call_end(); @@ -965,10 +804,8 @@ trace_screen_create(struct pipe_screen *screen) return &tr_scr->base; -#if 0 error3: FREE(tr_scr); -#endif error2: trace_dump_ret(ptr, screen); trace_dump_call_end(); diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h index fe5a0fa1909..9bfbe72e2c0 100644 --- a/src/gallium/drivers/trace/tr_screen.h +++ b/src/gallium/drivers/trace/tr_screen.h @@ -56,6 +56,7 @@ struct trace_screen struct pipe_screen base; struct pipe_screen *screen; + struct pipe_context *private_context; /* remote debugger */ struct trace_rbug *rbug; @@ -99,9 +100,6 @@ trace_enabled(void); struct trace_screen * trace_screen(struct pipe_screen *screen); -struct pipe_screen * -trace_screen_create(struct pipe_screen *screen); - void trace_screen_user_buffer_update(struct pipe_screen *screen, struct pipe_buffer *buffer); diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c index 5321d68ec0c..d818e21bb82 100644 --- a/src/gallium/drivers/trace/tr_texture.c +++ b/src/gallium/drivers/trace/tr_texture.c @@ -31,6 +31,7 @@ #include "util/u_simple_list.h" #include "tr_screen.h" +#include "tr_context.h" #include "tr_texture.h" @@ -124,8 +125,9 @@ trace_surface_destroy(struct trace_surface *tr_surf) struct pipe_transfer * -trace_transfer_create(struct trace_texture *tr_tex, - struct pipe_transfer *transfer) +trace_transfer_create(struct trace_context *tr_ctx, + struct trace_texture *tr_tex, + struct pipe_transfer *transfer) { struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); struct trace_transfer *tr_trans; @@ -142,8 +144,9 @@ trace_transfer_create(struct trace_texture *tr_tex, memcpy(&tr_trans->base, transfer, sizeof(struct pipe_transfer)); tr_trans->base.texture = NULL; - pipe_texture_reference(&tr_trans->base.texture, &tr_tex->base); tr_trans->transfer = transfer; + + pipe_texture_reference(&tr_trans->base.texture, &tr_tex->base); assert(tr_trans->base.texture == &tr_tex->base); trace_screen_add_to_list(tr_scr, transfers, tr_trans); @@ -151,21 +154,23 @@ trace_transfer_create(struct trace_texture *tr_tex, return &tr_trans->base; error: - transfer->texture->screen->tex_transfer_destroy(transfer); + tr_ctx->pipe->tex_transfer_destroy(tr_ctx->pipe, transfer); return NULL; } void -trace_transfer_destroy(struct trace_transfer *tr_trans) +trace_transfer_destroy(struct trace_context *tr_context, + struct trace_transfer *tr_trans) { - struct trace_screen *tr_scr = trace_screen(tr_trans->base.texture->screen); - struct pipe_screen *screen = tr_trans->transfer->texture->screen; + struct trace_screen *tr_scr = trace_screen(tr_context->base.screen); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; trace_screen_remove_from_list(tr_scr, transfers, tr_trans); pipe_texture_reference(&tr_trans->base.texture, NULL); - screen->tex_transfer_destroy(tr_trans->transfer); + context->tex_transfer_destroy(context, transfer); FREE(tr_trans); } diff --git a/src/gallium/drivers/trace/tr_texture.h b/src/gallium/drivers/trace/tr_texture.h index 395e523e73a..4dc95308a79 100644 --- a/src/gallium/drivers/trace/tr_texture.h +++ b/src/gallium/drivers/trace/tr_texture.h @@ -34,6 +34,7 @@ #include "tr_screen.h" +struct trace_context; struct trace_texture { @@ -60,6 +61,7 @@ struct trace_transfer struct pipe_transfer base; struct pipe_transfer *transfer; + struct pipe_context *pipe; struct tr_list list; @@ -112,11 +114,13 @@ void trace_surface_destroy(struct trace_surface *tr_surf); struct pipe_transfer * -trace_transfer_create(struct trace_texture *tr_tex, - struct pipe_transfer *transfer); +trace_transfer_create(struct trace_context *tr_ctx, + struct trace_texture *tr_tex, + struct pipe_transfer *transfer); void -trace_transfer_destroy(struct trace_transfer *tr_trans); +trace_transfer_destroy(struct trace_context *tr_ctx, + struct trace_transfer *tr_trans); #endif /* TR_TEXTURE_H_ */ |