From: Keith Whitwell Date: Sun, 1 Nov 2009 12:08:14 +0000 (+0000) Subject: i965g: more work on compilation -- surface management X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9b18ca095503eb80f02db55baf9c35aa69ae1cc9;p=mesa.git i965g: more work on compilation -- surface management --- diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 8067e20c968..471855ab63c 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -146,6 +146,8 @@ struct brw_blend_state { struct brw_cc3 cc3; struct brw_cc5 cc5; struct brw_cc6 cc6; + + struct brw_surf_ss0 ss0; }; @@ -501,15 +503,14 @@ struct brw_context const struct brw_rasterizer_state *rast; const struct brw_depth_stencil_state *zstencil; - const struct brw_texture *texture[PIPE_MAX_SAMPLERS]; const struct brw_sampler *sampler[PIPE_MAX_SAMPLERS]; - unsigned num_textures; + const struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; + unsigned num_vertex_elements; unsigned num_samplers; - - struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; + struct brw_texture *texture[PIPE_MAX_SAMPLERS]; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - unsigned num_vertex_elements; + unsigned num_textures; unsigned num_vertex_buffers; struct pipe_scissor_state scissor; diff --git a/src/gallium/drivers/i965/brw_defines.h b/src/gallium/drivers/i965/brw_defines.h index 544d36306cd..65cd71c939c 100644 --- a/src/gallium/drivers/i965/brw_defines.h +++ b/src/gallium/drivers/i965/brw_defines.h @@ -841,4 +841,9 @@ #define URB_SIZES(brw) (BRW_IS_IGDNG(brw) ? 1024 : \ (BRW_IS_G4X(brw) ? 384 : 256)) /* 512 bit units */ + +#define BRW_TILING_NONE 0 +#define BRW_TILING_Y 1 +#define BRW_TILING_X 2 + #endif diff --git a/src/gallium/drivers/i965/brw_screen.h b/src/gallium/drivers/i965/brw_screen.h index efa27db1e0f..844c6355d50 100644 --- a/src/gallium/drivers/i965/brw_screen.h +++ b/src/gallium/drivers/i965/brw_screen.h @@ -32,6 +32,7 @@ #include "pipe/p_screen.h" #include "brw_reg.h" +#include "brw_structs.h" struct brw_winsys_screen; @@ -68,10 +69,23 @@ struct brw_texture { struct pipe_texture base; - ubyte shader_swizzle; + struct brw_winsys_buffer *bo; + struct brw_surface_state ss; + + unsigned brw_target; + unsigned pitch; + unsigned tiling; + unsigned cpp; }; +struct brw_surface +{ + struct pipe_surface base; + struct brw_surface_state ss; + struct brw_winsys_buffer *bo; +}; + /* * Cast wrappers */ @@ -87,6 +101,12 @@ brw_transfer(struct pipe_transfer *transfer) return (struct brw_transfer *)transfer; } +static INLINE struct brw_surface * +brw_surface(struct pipe_surface *surface) +{ + return (struct brw_surface *)surface; +} + static INLINE struct brw_buffer * brw_buffer(struct pipe_buffer *buffer) { diff --git a/src/gallium/drivers/i965/brw_screen_surface.c b/src/gallium/drivers/i965/brw_screen_surface.c index e0df6cc629b..01d4b2d2b1a 100644 --- a/src/gallium/drivers/i965/brw_screen_surface.c +++ b/src/gallium/drivers/i965/brw_screen_surface.c @@ -2,6 +2,123 @@ #include "pipe/p_screen.h" #include "brw_screen.h" + +/** + * Sets up a surface state structure to point at the given region. + * While it is only used for the front/back buffer currently, it should be + * usable for further buffers when doing ARB_draw_buffer support. + */ +static void +brw_update_renderbuffer_surface(struct brw_context *brw, + struct gl_renderbuffer *rb, + unsigned int unit) +{ + struct brw_winsys_buffer *region_bo = NULL; + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + struct intel_region *region = irb ? irb->region : NULL; + struct { + unsigned int surface_type; + unsigned int surface_format; + unsigned int width, height, pitch, cpp; + GLubyte color_mask[4]; + GLboolean color_blend; + uint32_t tiling; + uint32_t draw_offset; + } key; + + memset(&key, 0, sizeof(key)); + + if (region != NULL) { + region_bo = region->buffer; + + key.surface_type = BRW_SURFACE_2D; + switch (irb->texformat->MesaFormat) { + case PIPE_FORMAT_ARGB8888: + key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + break; + case PIPE_FORMAT_RGB565: + key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; + break; + case PIPE_FORMAT_ARGB1555: + key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM; + break; + case PIPE_FORMAT_ARGB4444: + key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; + break; + default: + debug_printf("Bad renderbuffer format: %d\n", + irb->texformat->MesaFormat); + assert(0); + key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + return; + } + key.tiling = region->tiling; + if (brw->intel.intelScreen->driScrnPriv->dri2.enabled) { + key.width = rb->Width; + key.height = rb->Height; + } else { + key.width = region->width; + key.height = region->height; + } + key.pitch = region->pitch; + key.cpp = region->cpp; + key.draw_offset = region->draw_offset; /* cur 3d or cube face offset */ + } + + memcpy(key.color_mask, ctx->Color.ColorMask, + sizeof(key.color_mask)); + + key.color_blend = (!ctx->Color._LogicOpEnabled && + ctx->Color.BlendEnabled); + + brw->sws->bo_unreference(brw->wm.surf_bo[unit]); + brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &key, sizeof(key), + ®ion_bo, 1, + NULL); + + if (brw->wm.surf_bo[unit] == NULL) { + struct brw_surface_state surf; + + memset(&surf, 0, sizeof(surf)); + + surf.ss0.surface_format = key.surface_format; + surf.ss0.surface_type = key.surface_type; + if (key.tiling == I915_TILING_NONE) { + surf.ss1.base_addr = key.draw_offset; + } else { + uint32_t tile_offset = key.draw_offset % 4096; + + surf.ss1.base_addr = key.draw_offset - tile_offset; + + assert(BRW_IS_G4X(brw) || tile_offset == 0); + if (BRW_IS_G4X(brw)) { + if (key.tiling == I915_TILING_X) { + /* Note that the low bits of these fields are missing, so + * there's the possibility of getting in trouble. + */ + surf.ss5.x_offset = (tile_offset % 512) / key.cpp / 4; + surf.ss5.y_offset = tile_offset / 512 / 2; + } else { + surf.ss5.x_offset = (tile_offset % 128) / key.cpp / 4; + surf.ss5.y_offset = tile_offset / 128 / 2; + } + } + } + + if (region_bo != NULL) + surf.ss1.base_addr += region_bo->offset; /* reloc */ + + surf.ss2.width = key.width - 1; + surf.ss2.height = key.height - 1; + brw_set_surface_tiling(&surf, key.tiling); + surf.ss3.pitch = (key.pitch * key.cpp) - 1; + +} + + + struct brw_surface_id { unsigned face:3; unsigned zslice:13; diff --git a/src/gallium/drivers/i965/brw_screen_texture.c b/src/gallium/drivers/i965/brw_screen_texture.c index 50c30878c6f..3d069add6fc 100644 --- a/src/gallium/drivers/i965/brw_screen_texture.c +++ b/src/gallium/drivers/i965/brw_screen_texture.c @@ -36,6 +36,166 @@ #define FILE_DEBUG_FLAG DEBUG_MIPTREE + + +static GLuint translate_tex_target( unsigned target ) +{ + switch (target) { + case PIPE_TEXTURE_1D: + return BRW_SURFACE_1D; + + case PIPE_TEXTURE_2D: + return BRW_SURFACE_2D; + + case PIPE_TEXTURE_3D: + return BRW_SURFACE_3D; + + case PIPE_TEXTURE_CUBE: + return BRW_SURFACE_CUBE; + + default: + assert(0); + return BRW_SURFACE_1D; + } +} + + +static GLuint translate_tex_format( enum pipe_format pf ) +{ + switch( pf ) { + case PIPE_FORMAT_L8_UNORM: + return BRW_SURFACEFORMAT_L8_UNORM; + + case PIPE_FORMAT_I8_UNORM: + return BRW_SURFACEFORMAT_I8_UNORM; + + case PIPE_FORMAT_A8_UNORM: + return BRW_SURFACEFORMAT_A8_UNORM; + + case PIPE_FORMAT_A8L8_UNORM: + return BRW_SURFACEFORMAT_L8A8_UNORM; + + case PIPE_FORMAT_A8R8G8B8_UNORM: /* XXX */ + case PIPE_FORMAT_B8G8R8A8_UNORM: /* XXX */ + case PIPE_FORMAT_R8G8B8A8_UNORM: /* XXX */ + return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + + case PIPE_FORMAT_R8G8B8X8_UNORM: + return BRW_SURFACEFORMAT_R8G8B8X8_UNORM; + + case PIPE_FORMAT_R5G6B5_UNORM: + return BRW_SURFACEFORMAT_B5G6R5_UNORM; + + case PIPE_FORMAT_A1R5G5B5_UNORM: + return BRW_SURFACEFORMAT_B5G5R5A1_UNORM; + + case PIPE_FORMAT_A4R4G4B4_UNORM: + return BRW_SURFACEFORMAT_B4G4R4A4_UNORM; + + + case PIPE_FORMAT_L16_UNORM: + return BRW_SURFACEFORMAT_L16_UNORM; + + /* XXX: Z texturing: + case PIPE_FORMAT_I16_UNORM: + return BRW_SURFACEFORMAT_I16_UNORM; + */ + + /* XXX: Z texturing: + case PIPE_FORMAT_A16_UNORM: + return BRW_SURFACEFORMAT_A16_UNORM; + */ + + case PIPE_FORMAT_YCBCR_REV: + return BRW_SURFACEFORMAT_YCRCB_NORMAL; + + case PIPE_FORMAT_YCBCR: + return BRW_SURFACEFORMAT_YCRCB_SWAPUVY; + + /* XXX: Add FXT to gallium? + case PIPE_FORMAT_FXT1_RGBA: + return BRW_SURFACEFORMAT_FXT1; + */ + + case PIPE_FORMAT_DXT1_RGB: + return BRW_SURFACEFORMAT_DXT1_RGB; + + case PIPE_FORMAT_DXT1_RGBA: + return BRW_SURFACEFORMAT_BC1_UNORM; + + case PIPE_FORMAT_DXT3_RGBA: + return BRW_SURFACEFORMAT_BC2_UNORM; + + case PIPE_FORMAT_DXT5_RGBA: + return BRW_SURFACEFORMAT_BC3_UNORM; + + case PIPE_FORMAT_R8G8B8A8_SRGB: + return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB; + + case PIPE_FORMAT_A8L8_SRGB: + return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB; + + case PIPE_FORMAT_L8_SRGB: + return BRW_SURFACEFORMAT_L8_UNORM_SRGB; + + case PIPE_FORMAT_DXT1_SRGB: + return BRW_SURFACEFORMAT_BC1_UNORM_SRGB; + + /* XXX: which pipe depth formats does i965 suppport + */ + case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: + return BRW_SURFACEFORMAT_I24X8_UNORM; + +#if 0 + /* XXX: these different surface formats don't seem to + * make any difference for shadow sampler/compares. + */ + if (depth_mode == GL_INTENSITY) + return BRW_SURFACEFORMAT_I24X8_UNORM; + else if (depth_mode == GL_ALPHA) + return BRW_SURFACEFORMAT_A24X8_UNORM; + else + return BRW_SURFACEFORMAT_L24X8_UNORM; +#endif + + /* XXX: presumably for bump mapping. Add this to mesa state + * tracker? + */ + case PIPE_FORMAT_R8G8_SNORM: + return BRW_SURFACEFORMAT_R8G8_SNORM; + + case PIPE_FORMAT_R8G8B8A8_SNORM: + return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; + + default: + assert(0); + return 0; + } +} + +static void +brw_set_surface_tiling(struct brw_surface_state *surf, uint32_t tiling) +{ + switch (tiling) { + case BRW_TILING_NONE: + surf->ss3.tiled_surface = 0; + surf->ss3.tile_walk = 0; + break; + case BRW_TILING_X: + surf->ss3.tiled_surface = 1; + surf->ss3.tile_walk = BRW_TILEWALK_XMAJOR; + break; + case BRW_TILING_Y: + surf->ss3.tiled_surface = 1; + surf->ss3.tile_walk = BRW_TILEWALK_YMAJOR; + break; + } +} + + GLboolean brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt, uint32_t tiling) @@ -216,3 +376,58 @@ GLboolean brw_miptree_layout(struct brw_context *brw, return GL_TRUE; } + +static void brw_create_texture( struct pipe_screen *screen, + const pipe_texture *templ ) + +{ + + key.format = tex->base.format; + key.pitch = tex->pitch; + key.depth = tex->base.depth[0]; + key.bo = tex->buffer; + key.offset = 0; + + key.target = tex->brw_target; /* translated to BRW enum */ + //key.depthmode = 0; /* XXX: add this to gallium? or the state tracker? */ + key.last_level = tex->base.last_level; + key.width = tex->base.depth[0]; + key.height = tex->base.height[0]; + key.cpp = tex->cpp; + key.tiling = tex->tiling; + + + + surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; + surf.ss0.surface_type = translate_tex_target(key->target); + surf.ss0.surface_format = translate_tex_format(key->format /* , key->depthmode */ ); + + /* This is ok for all textures with channel width 8bit or less: + */ +/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ + assert(key->bo); + surf.ss1.base_addr = key->bo->offset; /* reloc */ + surf.ss2.mip_count = key->last_level; + surf.ss2.width = key->width - 1; + surf.ss2.height = key->height - 1; + brw_set_surface_tiling(&surf, key->tiling); + surf.ss3.pitch = (key->pitch * key->cpp) - 1; + surf.ss3.depth = key->depth - 1; + + surf.ss4.min_lod = 0; + + if (key->target == PIPE_TEXTURE_CUBE) { + surf.ss0.cube_pos_x = 1; + surf.ss0.cube_pos_y = 1; + surf.ss0.cube_pos_z = 1; + surf.ss0.cube_neg_x = 1; + surf.ss0.cube_neg_y = 1; + surf.ss0.cube_neg_z = 1; + } + +} + + + + + diff --git a/src/gallium/drivers/i965/brw_state.h b/src/gallium/drivers/i965/brw_state.h index 2275e9ad690..b47b04fd46f 100644 --- a/src/gallium/drivers/i965/brw_state.h +++ b/src/gallium/drivers/i965/brw_state.h @@ -94,19 +94,6 @@ const struct brw_tracked_state brw_indices; const struct brw_tracked_state brw_vertices; const struct brw_tracked_state brw_index_buffer; -/** - * Use same key for WM and VS surfaces. - */ -struct brw_surface_key { - unsigned target; - struct brw_winsys_buffer *bo; - GLint format; - GLint first_level, last_level; - GLint width, height, depth; - GLint pitch, cpp; - uint32_t tiling; - GLuint offset; -}; /*********************************************************************** * brw_state.c @@ -171,9 +158,6 @@ void brw_clear_batch_cache( struct brw_context *brw ); /*********************************************************************** * brw_wm_surface_state.c */ -struct brw_winsys_buffer * -brw_create_constant_surface( struct brw_context *brw, - struct brw_surface_key *key ); /*********************************************************************** * brw_state_debug.c diff --git a/src/gallium/drivers/i965/brw_state_cache.c b/src/gallium/drivers/i965/brw_state_cache.c index 4310d01ba2e..9cf44f7a5cc 100644 --- a/src/gallium/drivers/i965/brw_state_cache.c +++ b/src/gallium/drivers/i965/brw_state_cache.c @@ -179,7 +179,8 @@ brw_search_cache(struct brw_cache *cache, enum brw_cache_id cache_id, const void *key, GLuint key_size, - struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs, + struct brw_winsys_buffer **reloc_bufs, + GLuint nr_reloc_bufs, void *aux_return) { struct brw_cache_item *item; diff --git a/src/gallium/drivers/i965/brw_structs.h b/src/gallium/drivers/i965/brw_structs.h index f5d6a2599b4..bf10bc04de7 100644 --- a/src/gallium/drivers/i965/brw_structs.h +++ b/src/gallium/drivers/i965/brw_structs.h @@ -1048,7 +1048,7 @@ struct brw_sf_viewport */ struct brw_surface_state { - struct { + struct brw_surf_ss0 { GLuint cube_pos_z:1; GLuint cube_neg_z:1; GLuint cube_pos_y:1; @@ -1070,18 +1070,18 @@ struct brw_surface_state GLuint surface_type:3; /**< BRW_SURFACE_1D/2D/3D/CUBE */ } ss0; - struct { + struct brw_surf_ss1 { GLuint base_addr; } ss1; - struct { + struct brw_surf_ss2 { GLuint pad:2; GLuint mip_count:4; GLuint width:13; GLuint height:13; } ss2; - struct { + struct brw_surf_ss3 { GLuint tile_walk:1; GLuint tiled_surface:1; GLuint pad:1; @@ -1089,7 +1089,7 @@ struct brw_surface_state GLuint depth:11; } ss3; - struct { + struct brw_surf_ss4 { GLuint multisample_position_palette_index:3; GLuint pad1:1; GLuint num_multisamples:3; @@ -1099,7 +1099,7 @@ struct brw_surface_state GLuint min_lod:4; } ss4; - struct { + struct brw_surf_ss5 { GLuint pad1:16; GLuint llc_mapping:1; GLuint mlc_mapping:1; diff --git a/src/gallium/drivers/i965/brw_wm_surface_state.c b/src/gallium/drivers/i965/brw_wm_surface_state.c index 7157feb6f39..88485c76cb4 100644 --- a/src/gallium/drivers/i965/brw_wm_surface_state.c +++ b/src/gallium/drivers/i965/brw_wm_surface_state.c @@ -29,448 +29,49 @@ * Keith Whitwell */ +#include "pipe/p_format.h" #include "brw_batchbuffer.h" #include "brw_context.h" #include "brw_state.h" #include "brw_defines.h" +#include "brw_screen.h" -static GLuint translate_tex_target( GLenum target ) -{ - switch (target) { - case GL_TEXTURE_1D: - return BRW_SURFACE_1D; - - case GL_TEXTURE_RECTANGLE_NV: - return BRW_SURFACE_2D; - - case GL_TEXTURE_2D: - return BRW_SURFACE_2D; - - case GL_TEXTURE_3D: - return BRW_SURFACE_3D; - - case GL_TEXTURE_CUBE_MAP: - return BRW_SURFACE_CUBE; - - default: - assert(0); - return 0; - } -} - - -static GLuint translate_tex_format( GLuint mesa_format, - GLenum depth_mode ) -{ - switch( pipe_format ) { - case PIPE_FORMAT_L8_UNORM: - return BRW_SURFACEFORMAT_L8_UNORM; - - case PIPE_FORMAT_I8_UNORM: - return BRW_SURFACEFORMAT_I8_UNORM; - - case PIPE_FORMAT_A8_UNORM: - return BRW_SURFACEFORMAT_A8_UNORM; - - case PIPE_FORMAT_A8L8_UNORM: - return BRW_SURFACEFORMAT_L8A8_UNORM; - - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_R8G8B8A8_UNORM: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - - case PIPE_FORMAT_R8G8B8X8_UNORM: - return BRW_SURFACEFORMAT_R8G8B8X8_UNORM; - - case PIPE_FORMAT_: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - case PIPE_FORMAT_RGB565: - return BRW_SURFACEFORMAT_B5G6R5_UNORM; - - case PIPE_FORMAT_ARGB1555: - return BRW_SURFACEFORMAT_B5G5R5A1_UNORM; - - case PIPE_FORMAT_ARGB4444: - return BRW_SURFACEFORMAT_B4G4R4A4_UNORM; - - - case PIPE_FORMAT_L16_UNORM: - return BRW_SURFACEFORMAT_L16_UNORM; - - case PIPE_FORMAT_I16_UNORM: - return BRW_SURFACEFORMAT_I16_UNORM; - - case PIPE_FORMAT_A16_UNORM: - return BRW_SURFACEFORMAT_A16_UNORM; - - case PIPE_FORMAT_YCBCR_REV: - return BRW_SURFACEFORMAT_YCRCB_NORMAL; - - case PIPE_FORMAT_YCBCR: - return BRW_SURFACEFORMAT_YCRCB_SWAPUVY; - - case PIPE_FORMAT_RGB_FXT1: - case PIPE_FORMAT_RGBA_FXT1: - return BRW_SURFACEFORMAT_FXT1; - - case PIPE_FORMAT_RGB_DXT1: - return BRW_SURFACEFORMAT_DXT1_RGB; - - case PIPE_FORMAT_RGBA_DXT1: - return BRW_SURFACEFORMAT_BC1_UNORM; - - case PIPE_FORMAT_RGBA_DXT3: - return BRW_SURFACEFORMAT_BC2_UNORM; - - case PIPE_FORMAT_RGBA_DXT5: - return BRW_SURFACEFORMAT_BC3_UNORM; - - case PIPE_FORMAT_R8G8B8A8_SRGB: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB; - - case PIPE_FORMAT_A8L8_SRGB: - return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB; - - case PIPE_FORMAT_L8_SRGB: - return BRW_SURFACEFORMAT_L8_UNORM_SRGB; - - case PIPE_FORMAT_SRGB_DXT1: - return BRW_SURFACEFORMAT_BC1_UNORM_SRGB; - - case PIPE_FORMAT_S8_Z24: - /* XXX: these different surface formats don't seem to - * make any difference for shadow sampler/compares. - */ - if (depth_mode == GL_INTENSITY) - return BRW_SURFACEFORMAT_I24X8_UNORM; - else if (depth_mode == GL_ALPHA) - return BRW_SURFACEFORMAT_A24X8_UNORM; - else - return BRW_SURFACEFORMAT_L24X8_UNORM; - - case PIPE_FORMAT_DUDV8: - return BRW_SURFACEFORMAT_R8G8_SNORM; - - case PIPE_FORMAT_SIGNED_RGBA8888_REV: - return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; - - default: - assert(0); - return 0; - } -} - -static void -brw_set_surface_tiling(struct brw_surface_state *surf, uint32_t tiling) -{ - switch (tiling) { - case I915_TILING_NONE: - surf->ss3.tiled_surface = 0; - surf->ss3.tile_walk = 0; - break; - case I915_TILING_X: - surf->ss3.tiled_surface = 1; - surf->ss3.tile_walk = BRW_TILEWALK_XMAJOR; - break; - case I915_TILING_Y: - surf->ss3.tiled_surface = 1; - surf->ss3.tile_walk = BRW_TILEWALK_YMAJOR; - break; - } -} - -static struct brw_winsys_buffer * -brw_create_texture_surface( struct brw_context *brw, - struct brw_surface_key *key ) -{ - struct brw_surface_state surf; - struct brw_winsys_buffer *bo; - - memset(&surf, 0, sizeof(surf)); - - surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - surf.ss0.surface_type = translate_tex_target(key->target); - if (key->bo) { - surf.ss0.surface_format = translate_tex_format(key->format, - key->internal_format, - key->depthmode); - } - else { - switch (key->depth) { - case 32: - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - break; - default: - case 24: - surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8X8_UNORM; - break; - case 16: - surf.ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; - break; - } - } - - /* This is ok for all textures with channel width 8bit or less: - */ -/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ - if (key->bo) - surf.ss1.base_addr = key->bo->offset; /* reloc */ - else - surf.ss1.base_addr = key->offset; - - surf.ss2.mip_count = key->last_level; - surf.ss2.width = key->width - 1; - surf.ss2.height = key->height - 1; - brw_set_surface_tiling(&surf, key->tiling); - surf.ss3.pitch = (key->pitch * key->cpp) - 1; - surf.ss3.depth = key->depth - 1; - - surf.ss4.min_lod = 0; - - if (key->target == GL_TEXTURE_CUBE_MAP) { - surf.ss0.cube_pos_x = 1; - surf.ss0.cube_pos_y = 1; - surf.ss0.cube_pos_z = 1; - surf.ss0.cube_neg_x = 1; - surf.ss0.cube_neg_y = 1; - surf.ss0.cube_neg_z = 1; - } - - bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, - key, sizeof(*key), - &key->bo, key->bo ? 1 : 0, - &surf, sizeof(surf), - NULL, NULL); - - if (key->bo) { - /* Emit relocation to surface contents */ - dri_bo_emit_reloc(bo, - I915_GEM_DOMAIN_SAMPLER, 0, - 0, - offsetof(struct brw_surface_state, ss1), - key->bo); - } - return bo; -} static void -brw_update_texture_surface( struct brw_context *brw, GLuint unit ) +brw_update_texture_surface( struct brw_context *brw, + struct brw_texture *tex, + GLuint surf ) { - struct pipe_texture *tex = brw->texture[unit]; - struct brw_surface_key key; - const GLuint surf = SURF_INDEX_TEXTURE(unit); - - memset(&key, 0, sizeof(key)); - - key.format = tex->base.format; - key.pitch = tex->pitch; - key.depth = tex->base.depth[0]; - key.bo = tex->buffer; - key.offset = 0; - - key.target = tObj->target; /* translated to BRW enum */ - /* key.depthmode = tObj->DepthMode; */ /* XXX: add this to gallium? or the state tracker? */ - key.first_level = 0; - key.last_level = tex->base.last_level; - key.width = tex->base.depth[0]; - key.height = tex->base.height[0]; - key.cpp = tex->cpp; - key.tiling = tex->tiling; - - brw->sws->bo_unreference(brw->wm.surf_bo[surf]); brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache, BRW_SS_SURFACE, - &key, sizeof(key), - &key.bo, key.bo ? 1 : 0, + &tex->ss, sizeof tex->ss, + &tex->bo, 1, NULL); - if (brw->wm.surf_bo[surf] == NULL) { - brw->wm.surf_bo[surf] = brw_create_texture_surface(brw, &key); - } -} - - - -/** - * Create the constant buffer surface. Vertex/fragment shader constants will be - * read from this buffer with Data Port Read instructions/messages. - */ -struct brw_winsys_buffer * -brw_create_constant_surface( struct brw_context *brw, - struct brw_surface_key *key ) -{ - const GLint w = key->width - 1; - struct brw_surface_state surf; - struct brw_winsys_buffer *bo; - - memset(&surf, 0, sizeof(surf)); - - surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; - surf.ss0.surface_type = BRW_SURFACE_BUFFER; - surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; - - assert(key->bo); - if (key->bo) - surf.ss1.base_addr = key->bo->offset; /* reloc */ - else - surf.ss1.base_addr = key->offset; - - surf.ss2.width = w & 0x7f; /* bits 6:0 of size or width */ - surf.ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */ - surf.ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */ - surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */ - brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */ - - bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, - key, sizeof(*key), - &key->bo, key->bo ? 1 : 0, - &surf, sizeof(surf), - NULL, NULL); - if (key->bo) { + if (brw->wm.surf_bo[surf] == NULL) { + brw->wm.surf_bo[surf] = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, + &tex->ss, sizeof tex->ss, + &tex->bo, 1, + &tex->ss, sizeof tex->ss, + NULL, NULL); + /* Emit relocation to surface contents */ - dri_bo_emit_reloc(bo, - I915_GEM_DOMAIN_SAMPLER, 0, - 0, - offsetof(struct brw_surface_state, ss1), - key->bo); + brw->sws->bo_emit_reloc(brw->wm.surf_bo[surf], + I915_GEM_DOMAIN_SAMPLER, 0, + 0, + offsetof(struct brw_surface_state, ss1), + tex->bo); } - - return bo; } -/* Creates a new WM constant buffer reflecting the current fragment program's - * constants, if needed by the fragment program. - * - * Otherwise, constants go through the CURBEs using the brw_constant_buffer - * state atom. - */ -static drm_intel_bo * -brw_wm_update_constant_buffer(struct brw_context *brw) -{ - struct brw_fragment_program *fp = - (struct brw_fragment_program *) brw->fragment_program; - const struct gl_program_parameter_list *params = fp->program.Base.Parameters; - const int size = params->NumParameters * 4 * sizeof(GLfloat); - drm_intel_bo *const_buffer; - /* BRW_NEW_FRAGMENT_PROGRAM */ - if (!fp->use_const_buffer) - return NULL; - const_buffer = drm_intel_bo_alloc(intel->bufmgr, - BRW_BUFFER_TYPE_SHADER_CONSTANTS, - size, 64); - /* _NEW_PROGRAM_CONSTANTS */ - dri_bo_subdata(const_buffer, 0, size, params->ParameterValues); - return const_buffer; -} -/** - * Update the surface state for a WM constant buffer. - * The constant buffer will be (re)allocated here if needed. - */ -static void -brw_update_wm_constant_surface( struct brw_context *brw, - GLuint surf) -{ - struct brw_context *brw = brw_context(ctx); - struct brw_surface_key key; - struct brw_fragment_program *fp = - (struct brw_fragment_program *) brw->fragment_program; - const struct gl_program_parameter_list *params = - fp->program.Base.Parameters; - - /* If we're in this state update atom, we need to update WM constants, so - * free the old buffer and create a new one for the new contents. - */ - brw->sws->bo_unreference(fp->const_buffer); - fp->const_buffer = brw_wm_update_constant_buffer(brw); - - /* If there's no constant buffer, then no surface BO is needed to point at - * it. - */ - if (fp->const_buffer == 0) { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; - return; - } - - memset(&key, 0, sizeof(key)); - - key.format = PIPE_FORMAT_RGBA_FLOAT32; - key.internal_format = GL_RGBA; - key.bo = fp->const_buffer; - key.depthmode = GL_NONE; - key.pitch = params->NumParameters; - key.width = params->NumParameters; - key.height = 1; - key.depth = 1; - key.cpp = 16; - - /* - printf("%s:\n", __FUNCTION__); - printf(" width %d height %d depth %d cpp %d pitch %d\n", - key.width, key.height, key.depth, key.cpp, key.pitch); - */ - - brw->sws->bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache, - BRW_SS_SURFACE, - &key, sizeof(key), - &key.bo, key.bo ? 1 : 0, - NULL); - if (brw->wm.surf_bo[surf] == NULL) { - brw->wm.surf_bo[surf] = brw_create_constant_surface(brw, &key); - } - brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; -} - -/** - * Updates surface / buffer for fragment shader constant buffer, if - * one is required. - * - * This consumes the state updates for the constant buffer, and produces - * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for - * inclusion in the binding table. - */ -static void prepare_wm_constant_surface(struct brw_context *brw ) -{ - struct brw_fragment_program *fp = - (struct brw_fragment_program *) brw->fragment_program; - GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER; - - drm_intel_bo_unreference(fp->const_buffer); - fp->const_buffer = brw_wm_update_constant_buffer(brw); - - /* If there's no constant buffer, then no surface BO is needed to point at - * it. - */ - if (fp->const_buffer == 0) { - if (brw->wm.surf_bo[surf] != NULL) { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; - brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; - } - return; - } - - brw_update_wm_constant_surface(ctx, surf); -} - -const struct brw_tracked_state brw_wm_constant_surface = { - .dirty = { - .mesa = (_NEW_PROGRAM_CONSTANTS), - .brw = (BRW_NEW_FRAGMENT_PROGRAM), - .cache = 0 - }, - .prepare = prepare_wm_constant_surface, -}; /** @@ -480,142 +81,46 @@ const struct brw_tracked_state brw_wm_constant_surface = { */ static void brw_update_renderbuffer_surface(struct brw_context *brw, - struct gl_renderbuffer *rb, + struct brw_surface *surface, unsigned int unit) { - struct brw_winsys_buffer *region_bo = NULL; - struct intel_renderbuffer *irb = intel_renderbuffer(rb); - struct intel_region *region = irb ? irb->region : NULL; - struct { - unsigned int surface_type; - unsigned int surface_format; - unsigned int width, height, pitch, cpp; - GLubyte color_mask[4]; - GLboolean color_blend; - uint32_t tiling; - uint32_t draw_offset; - } key; - - memset(&key, 0, sizeof(key)); - - if (region != NULL) { - region_bo = region->buffer; - - key.surface_type = BRW_SURFACE_2D; - switch (irb->texformat->MesaFormat) { - case PIPE_FORMAT_ARGB8888: - key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - break; - case PIPE_FORMAT_RGB565: - key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; - break; - case PIPE_FORMAT_ARGB1555: - key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM; - break; - case PIPE_FORMAT_ARGB4444: - key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; - break; - default: - debug_printf("Bad renderbuffer format: %d\n", - irb->texformat->MesaFormat); - assert(0); - key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - return; - } - key.tiling = region->tiling; - if (brw->intel.intelScreen->driScrnPriv->dri2.enabled) { - key.width = rb->Width; - key.height = rb->Height; - } else { - key.width = region->width; - key.height = region->height; - } - key.pitch = region->pitch; - key.cpp = region->cpp; - key.draw_offset = region->draw_offset; /* cur 3d or cube face offset */ - } else { - key.surface_type = BRW_SURFACE_NULL; - key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - key.tiling = I915_TILING_X; - key.width = 1; - key.height = 1; - key.cpp = 4; - key.draw_offset = 0; - } - memcpy(key.color_mask, ctx->Color.ColorMask, - sizeof(key.color_mask)); - key.color_blend = (!ctx->Color._LogicOpEnabled && - ctx->Color.BlendEnabled); + struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0; + struct brw_surface_state ss; + + /* Surfaces are potentially shared between contexts, so can't + * scribble the in-place ss0 value in the surface. + */ + memcpy(&ss, &surface->ss, sizeof ss); + + ss.ss0.color_blend = blend_ss0.color_blend; + ss.ss0.writedisable_blue = blend_ss0.writedisable_blue; + ss.ss0.writedisable_green = blend_ss0.writedisable_green; + ss.ss0.writedisable_red = blend_ss0.writedisable_red; + ss.ss0.writedisable_alpha = blend_ss0.writedisable_alpha; brw->sws->bo_unreference(brw->wm.surf_bo[unit]); brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache, BRW_SS_SURFACE, - &key, sizeof(key), - ®ion_bo, 1, + &ss, sizeof(ss), + &surface->bo, 1, NULL); if (brw->wm.surf_bo[unit] == NULL) { - struct brw_surface_state surf; - - memset(&surf, 0, sizeof(surf)); - - surf.ss0.surface_format = key.surface_format; - surf.ss0.surface_type = key.surface_type; - if (key.tiling == I915_TILING_NONE) { - surf.ss1.base_addr = key.draw_offset; - } else { - uint32_t tile_offset = key.draw_offset % 4096; - - surf.ss1.base_addr = key.draw_offset - tile_offset; - - assert(BRW_IS_G4X(brw) || tile_offset == 0); - if (BRW_IS_G4X(brw)) { - if (key.tiling == I915_TILING_X) { - /* Note that the low bits of these fields are missing, so - * there's the possibility of getting in trouble. - */ - surf.ss5.x_offset = (tile_offset % 512) / key.cpp / 4; - surf.ss5.y_offset = tile_offset / 512 / 2; - } else { - surf.ss5.x_offset = (tile_offset % 128) / key.cpp / 4; - surf.ss5.y_offset = tile_offset / 128 / 2; - } - } - } - if (region_bo != NULL) - surf.ss1.base_addr += region_bo->offset; /* reloc */ - - surf.ss2.width = key.width - 1; - surf.ss2.height = key.height - 1; - brw_set_surface_tiling(&surf, key.tiling); - surf.ss3.pitch = (key.pitch * key.cpp) - 1; - - /* _NEW_COLOR */ - surf.ss0.color_blend = key.color_blend; - surf.ss0.writedisable_red = !key.color_mask[0]; - surf.ss0.writedisable_green = !key.color_mask[1]; - surf.ss0.writedisable_blue = !key.color_mask[2]; - surf.ss0.writedisable_alpha = !key.color_mask[3]; - - /* Key size will never match key size for textures, so we're safe. */ + brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, - &key, sizeof(key), - ®ion_bo, 1, - &surf, sizeof(surf), + &ss, sizeof ss, + &surface->bo, 1, + &ss, sizeof ss, NULL, NULL); - if (region_bo != NULL) { - /* We might sample from it, and we might render to it, so flag - * them both. We might be able to figure out from other state - * a more restrictive relocation to emit. - */ - drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit], - offsetof(struct brw_surface_state, ss1), - region_bo, - surf.ss1.base_addr - region_bo->offset, - I915_GEM_DOMAIN_RENDER, - I915_GEM_DOMAIN_RENDER); - } + + /* XXX: we will only be rendering to this surface: + */ + brw->sws->bo_emit_reloc(brw->wm.surf_bo[unit], + I915_GEM_DOMAIN_RENDER, 0, + ss.ss1.base_addr - surface->bo->offset, /* XXX */ + offsetof(struct brw_surface_state, ss1), + surface->bo); } } @@ -631,21 +136,21 @@ brw_wm_get_binding_table(struct brw_context *brw) assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF); + /* Note there is no key for this search beyond the values in the + * relocation array: + */ bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, NULL, 0, brw->wm.surf_bo, brw->wm.nr_surfaces, NULL); if (bind_bo == NULL) { - GLuint data_size = brw->wm.nr_surfaces * sizeof(GLuint); uint32_t data[BRW_WM_MAX_SURF]; + GLuint data_size = brw->wm.nr_surfaces * sizeof data[0]; int i; for (i = 0; i < brw->wm.nr_surfaces; i++) - if (brw->wm.surf_bo[i]) - data[i] = brw->wm.surf_bo[i]->offset; - else - data[i] = 0; + data[i] = brw->wm.surf_bo[i]->offset; bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, NULL, 0, @@ -654,70 +159,79 @@ brw_wm_get_binding_table(struct brw_context *brw) NULL, NULL); /* Emit binding table relocations to surface state */ - for (i = 0; i < BRW_WM_MAX_SURF; i++) { - if (brw->wm.surf_bo[i] != NULL) { - dri_bo_emit_reloc(bind_bo, - I915_GEM_DOMAIN_INSTRUCTION, 0, - 0, - i * sizeof(GLuint), - brw->wm.surf_bo[i]); - } + for (i = 0; i < brw->wm.nr_surfaces; i++) { + brw->sws->bo_emit_reloc(bind_bo, + I915_GEM_DOMAIN_INSTRUCTION, 0, + 0, + i * sizeof(GLuint), + brw->wm.surf_bo[i]); } } return bind_bo; } -static void prepare_wm_surfaces(struct brw_context *brw ) +static int prepare_wm_surfaces(struct brw_context *brw ) { GLuint i; - int old_nr_surfaces; - - /* _NEW_BUFFERS */ - /* Update surfaces for drawing buffers */ - if (ctx->DrawBuffer->_NumColorDrawBuffers >= 1) { - for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - brw_update_renderbuffer_surface(brw, - ctx->DrawBuffer->_ColorDrawBuffers[i], - i); - } - } else { - brw_update_renderbuffer_surface(brw, NULL, 0); + int nr_surfaces = 0; + + /* Unreference old buffers + */ + for (i = 0; i < brw->wm.nr_surfaces; i++) { + brw->sws->bo_unreference(brw->wm.surf_bo[i]); + brw->wm.surf_bo[i] = NULL; } - old_nr_surfaces = brw->wm.nr_surfaces; - brw->wm.nr_surfaces = PIPE_MAX_COLOR_BUFS; - if (brw->wm.surf_bo[SURF_INDEX_FRAG_CONST_BUFFER] != NULL) - brw->wm.nr_surfaces = SURF_INDEX_FRAG_CONST_BUFFER + 1; + /* PIPE_NEW_COLOR_BUFFERS | PIPE_NEW_BLEND + * + * Update surfaces for drawing buffers. Mixes in colormask and + * blend state. + * + * XXX: no color buffer case + */ + for (i = 0; i < brw->curr.fb.nr_cbufs; i++) { + brw_update_renderbuffer_surface(brw, + brw_surface(brw->curr.fb.cbufs[i]), + nr_surfaces++); + } - /* Update surfaces for textures */ - for (i = 0; i < BRW_MAX_TEX_UNIT; i++) { - const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; - const GLuint surf = SURF_INDEX_TEXTURE(i); + /* PIPE_NEW_TEXTURE + */ + for (i = 0; i < brw->curr.num_textures; i++) { + brw_update_texture_surface(brw, + brw->curr.texture[i], + nr_surfaces++); + } - /* _NEW_TEXTURE, BRW_NEW_TEXDATA */ - if (texUnit->_ReallyEnabled) { - brw_update_texture_surface(ctx, i); - brw->wm.nr_surfaces = surf + 1; - } else { - brw->sws->bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; - } + /* PIPE_NEW_FRAGMENT_CONSTANTS + */ +#if 0 + if (brw->curr.fragment_constants) { + brw_update_fragment_constant_surface(brw, + brw->curr.fragment_constants, + nr_surfaces++); } +#endif brw->sws->bo_unreference(brw->wm.bind_bo); brw->wm.bind_bo = brw_wm_get_binding_table(brw); - if (brw->wm.nr_surfaces != old_nr_surfaces) + if (brw->wm.nr_surfaces != nr_surfaces) { + brw->wm.nr_surfaces = nr_surfaces; brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES; + } + + return 0; } const struct brw_tracked_state brw_wm_surfaces = { .dirty = { - .mesa = (_NEW_COLOR | - _NEW_TEXTURE | - _NEW_BUFFERS), + .mesa = (PIPE_NEW_COLOR_BUFFERS | + PIPE_NEW_BOUND_TEXTURES | + PIPE_NEW_FRAGMENT_CONSTANTS | + PIPE_NEW_BLEND), .brw = (BRW_NEW_CONTEXT | BRW_NEW_WM_SURFACES), .cache = 0