i965g: more work on compilation -- surface management

This commit is contained in:
Keith Whitwell 2009-11-01 12:08:14 +00:00
parent e7b7600082
commit 9b18ca0955
9 changed files with 474 additions and 617 deletions

View file

@ -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;
unsigned num_samplers;
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
const struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
unsigned num_vertex_elements;
unsigned num_samplers;
struct brw_texture *texture[PIPE_MAX_SAMPLERS];
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
unsigned num_textures;
unsigned num_vertex_buffers;
struct pipe_scissor_state scissor;

View file

@ -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

View file

@ -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)
{

View file

@ -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),
&region_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;

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -29,448 +29,49 @@
* Keith Whitwell <keith@tungstengraphics.com>
*/
#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)
brw_update_texture_surface( struct brw_context *brw,
struct brw_texture *tex,
GLuint surf )
{
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 )
{
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) {
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;
struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
struct brw_surface_state ss;
memset(&key, 0, sizeof(key));
/* Surfaces are potentially shared between contexts, so can't
* scribble the in-place ss0 value in the surface.
*/
memcpy(&ss, &surface->ss, sizeof ss);
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);
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),
&region_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),
&region_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;
int nr_surfaces = 0;
/* _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);
/* 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;
/* 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);
/* _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_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++);
}
/* PIPE_NEW_TEXTURE
*/
for (i = 0; i < brw->curr.num_textures; i++) {
brw_update_texture_surface(brw,
brw->curr.texture[i],
nr_surfaces++);
}
/* 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