diff options
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_wm.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm.c | 283 |
1 files changed, 137 insertions, 146 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 1497dc7968..10f38e02a4 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -29,67 +29,31 @@ * Keith Whitwell <keith@tungstengraphics.com> */ - +#include "main/texformat.h" #include "brw_context.h" #include "brw_util.h" #include "brw_wm.h" #include "brw_state.h" -#include "brw_hal.h" +/** Return number of src args for given instruction */ GLuint brw_wm_nr_args( GLuint opcode ) { switch (opcode) { - case WM_PIXELXY: - case OPCODE_ABS: - case OPCODE_FLR: - case OPCODE_FRC: - case OPCODE_SWZ: - case OPCODE_MOV: - case OPCODE_COS: - case OPCODE_EX2: - case OPCODE_LG2: - case OPCODE_RCP: - case OPCODE_RSQ: - case OPCODE_SIN: - case OPCODE_SCS: - case OPCODE_TEX: - case OPCODE_TXB: - case OPCODE_TXP: - case OPCODE_KIL: - case OPCODE_LIT: - case WM_CINTERP: - case WM_WPOSXY: + case WM_CINTERP: + case WM_WPOSXY: return 1; - - case OPCODE_POW: - case OPCODE_SUB: - case OPCODE_SGE: - case OPCODE_SLT: - case OPCODE_ADD: - case OPCODE_MAX: - case OPCODE_MIN: - case OPCODE_MUL: - case OPCODE_XPD: - case OPCODE_DP3: - case OPCODE_DP4: - case OPCODE_DPH: - case OPCODE_DST: - case WM_LINTERP: + case WM_LINTERP: case WM_DELTAXY: case WM_PIXELW: return 2; - case WM_FB_WRITE: - case WM_PINTERP: - case OPCODE_MAD: - case OPCODE_CMP: - case OPCODE_LRP: + case WM_PINTERP: return 3; - default: - return 0; + assert(opcode < MAX_OPCODE); + return _mesa_num_inst_src_regs(opcode); } } @@ -116,46 +80,19 @@ GLuint brw_wm_is_scalar_result( GLuint opcode ) } -static void brw_wm_pass_hal (struct brw_wm_compile *c) -{ - static void (*hal_wm_pass) (struct brw_wm_compile *c); - static GLboolean hal_tried; - - if (!hal_tried) - { - hal_wm_pass = brw_hal_find_symbol ("intel_hal_wm_pass"); - hal_tried = 1; - } - if (hal_wm_pass) - (*hal_wm_pass) (c); -} - -static void do_wm_prog( struct brw_context *brw, - struct brw_fragment_program *fp, - struct brw_wm_prog_key *key) +/** + * Do GPU code generation for non-GLSL shader. non-GLSL shaders have + * no flow control instructions so we can more readily do SSA-style + * optimizations. + */ +static void +brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c) { - struct brw_wm_compile *c; - const GLuint *program; - GLuint program_size; - - c = brw->wm.compile_data; - if (c == NULL) { - brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data)); - c = brw->wm.compile_data; - } else { - memset(c, 0, sizeof(*brw->wm.compile_data)); - } - memcpy(&c->key, key, sizeof(*key)); - - c->fp = fp; - c->env_param = brw->intel.ctx.FragmentProgram.Parameters; - - /* Augment fragment program. Add instructions for pre- and * post-fragment-program tasks such as interpolation and fogging. */ brw_wm_pass_fp(c); - + /* Translate to intermediate representation. Build register usage * chains. */ @@ -165,45 +102,78 @@ static void do_wm_prog( struct brw_context *brw, */ brw_wm_pass1(c); - /* Hal optimization - */ - brw_wm_pass_hal (c); - /* Register allocation. */ - c->grf_limit = BRW_WM_MAX_GRF/2; - - /* This is where we start emitting gen4 code: - */ - brw_init_compile(&c->func); + c->grf_limit = BRW_WM_MAX_GRF / 2; brw_wm_pass2(c); c->prog_data.total_grf = c->max_wm_grf; if (c->last_scratch) { - c->prog_data.total_scratch = - c->last_scratch + 0x40; - } else { + c->prog_data.total_scratch = c->last_scratch + 0x40; + } + else { c->prog_data.total_scratch = 0; } /* Emit GEN4 code. */ brw_wm_emit(c); +} + + +/** + * All Mesa program -> GPU code generation goes through this function. + * Depending on the instructions used (i.e. flow control instructions) + * we'll use one of two code generators. + */ +static void do_wm_prog( struct brw_context *brw, + struct brw_fragment_program *fp, + struct brw_wm_prog_key *key) +{ + struct brw_wm_compile *c; + const GLuint *program; + GLuint program_size; + + c = brw->wm.compile_data; + if (c == NULL) { + brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data)); + c = brw->wm.compile_data; + } else { + memset(c, 0, sizeof(*brw->wm.compile_data)); + } + memcpy(&c->key, key, sizeof(*key)); + + c->fp = fp; + c->env_param = brw->intel.ctx.FragmentProgram.Parameters; + + brw_init_compile(brw, &c->func); + + /* + * Shader which use GLSL features such as flow control are handled + * differently from "simple" shaders. + */ + if (brw_wm_is_glsl(&c->fp->program)) { + brw_wm_glsl_emit(brw, c); + } + else { + brw_wm_non_glsl_emit(brw, c); + } + + if (INTEL_DEBUG & DEBUG_WM) + fprintf(stderr, "\n"); /* get the program */ program = brw_get_program(&c->func, &program_size); - /* - */ - brw->wm.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_WM_PROG], - &c->key, - sizeof(c->key), - program, - program_size, - &c->prog_data, - &brw->wm.prog_data ); + dri_bo_unreference(brw->wm.prog_bo); + brw->wm.prog_bo = brw_upload_cache( &brw->cache, BRW_WM_PROG, + &c->key, sizeof(c->key), + NULL, 0, + program, program_size, + &c->prog_data, + &brw->wm.prog_data ); } @@ -211,8 +181,9 @@ static void do_wm_prog( struct brw_context *brw, static void brw_wm_populate_key( struct brw_context *brw, struct brw_wm_prog_key *key ) { + GLcontext *ctx = &brw->intel.ctx; /* BRW_NEW_FRAGMENT_PROGRAM */ - struct brw_fragment_program *fp = + const struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program; GLuint lookup = 0; GLuint line_aa; @@ -224,56 +195,50 @@ static void brw_wm_populate_key( struct brw_context *brw, */ /* _NEW_COLOR */ if (fp->program.UsesKill || - brw->attribs.Color->AlphaEnabled) + ctx->Color.AlphaEnabled) lookup |= IZ_PS_KILL_ALPHATEST_BIT; if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPR)) lookup |= IZ_PS_COMPUTES_DEPTH_BIT; /* _NEW_DEPTH */ - if (brw->attribs.Depth->Test) + if (ctx->Depth.Test) lookup |= IZ_DEPTH_TEST_ENABLE_BIT; - if (brw->attribs.Depth->Test && - brw->attribs.Depth->Mask) /* ?? */ + if (ctx->Depth.Test && + ctx->Depth.Mask) /* ?? */ lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; /* _NEW_STENCIL */ - if (brw->attribs.Stencil->Enabled) { + if (ctx->Stencil.Enabled) { lookup |= IZ_STENCIL_TEST_ENABLE_BIT; - if (brw->attribs.Stencil->WriteMask[0] || - (brw->attribs.Stencil->TestTwoSide && brw->attribs.Stencil->WriteMask[1])) + if (ctx->Stencil.WriteMask[0] || + ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; } - /* XXX: when should this be disabled? - */ - if (1) - lookup |= IZ_EARLY_DEPTH_TEST_BIT; - - line_aa = AA_NEVER; /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ - if (brw->attribs.Line->SmoothFlag) { + if (ctx->Line.SmoothFlag) { if (brw->intel.reduced_primitive == GL_LINES) { line_aa = AA_ALWAYS; } else if (brw->intel.reduced_primitive == GL_TRIANGLES) { - if (brw->attribs.Polygon->FrontMode == GL_LINE) { + if (ctx->Polygon.FrontMode == GL_LINE) { line_aa = AA_SOMETIMES; - if (brw->attribs.Polygon->BackMode == GL_LINE || - (brw->attribs.Polygon->CullFlag && - brw->attribs.Polygon->CullFaceMode == GL_BACK)) + if (ctx->Polygon.BackMode == GL_LINE || + (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode == GL_BACK)) line_aa = AA_ALWAYS; } - else if (brw->attribs.Polygon->BackMode == GL_LINE) { + else if (ctx->Polygon.BackMode == GL_LINE) { line_aa = AA_SOMETIMES; - if ((brw->attribs.Polygon->CullFlag && - brw->attribs.Polygon->CullFaceMode == GL_FRONT)) + if ((ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode == GL_FRONT)) line_aa = AA_ALWAYS; } } @@ -285,37 +250,64 @@ static void brw_wm_populate_key( struct brw_context *brw, /* BRW_NEW_WM_INPUT_DIMENSIONS */ - key->projtex_mask = brw->wm.input_size_masks[4-1]; + key->projtex_mask = brw->wm.input_size_masks[4-1] >> (FRAG_ATTRIB_TEX0 - FRAG_ATTRIB_WPOS); /* _NEW_LIGHT */ - key->flat_shade = (brw->attribs.Light->ShadeModel == GL_FLAT); + key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); /* _NEW_TEXTURE */ for (i = 0; i < BRW_MAX_TEX_UNIT; i++) { - const struct gl_texture_unit *unit = &brw->attribs.Texture->Unit[i]; - const struct gl_texture_object *t = unit->_Current; + const struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; if (unit->_ReallyEnabled) { - - if (t->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && - t->Image[0][t->BaseLevel]->_BaseFormat == GL_DEPTH_COMPONENT) { - key->shadowtex_mask |= 1<<i; + const struct gl_texture_object *t = unit->_Current; + const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; + if (img->InternalFormat == GL_YCBCR_MESA) { + key->yuvtex_mask |= 1 << i; + if (img->TexFormat->MesaFormat == MESA_FORMAT_YCBCR) + key->yuvtex_swap_mask |= 1 << i; } - if (t->Image[0][t->BaseLevel]->InternalFormat == GL_YCBCR_MESA) - key->yuvtex_mask |= 1<<i; + key->tex_swizzles[i] = t->_Swizzle; + } + else { + key->tex_swizzles[i] = SWIZZLE_NOOP; } } - - /* Extra info: + /* Shadow */ + key->shadowtex_mask = fp->program.Base.ShadowSamplers; + + /* _NEW_BUFFERS */ + /* + * Include the draw buffer origin and height so that we can calculate + * fragment position values relative to the bottom left of the drawable, + * from the incoming screen origin relative position we get as part of our + * payload. + * + * We could avoid recompiling by including this as a constant referenced by + * our program, but if we were to do that it would also be nice to handle + * getting that constant updated at batchbuffer submit time (when we + * hold the lock and know where the buffer really is) rather than at emit + * time when we don't hold the lock and are just guessing. We could also + * just avoid using this as key data if the program doesn't use + * fragment.position. + * + * This pretty much becomes moot with DRI2 and redirected buffers anyway, + * as our origins will always be zero then. */ - key->program_string_id = fp->id; + if (brw->intel.driDrawable != NULL) { + key->origin_x = brw->intel.driDrawable->x; + key->origin_y = brw->intel.driDrawable->y; + key->drawable_height = brw->intel.driDrawable->h; + } + /* The unique fragment program ID */ + key->program_string_id = fp->id; } -static void brw_upload_wm_prog( struct brw_context *brw ) +static void brw_prepare_wm_prog(struct brw_context *brw) { struct brw_wm_prog_key key; struct brw_fragment_program *fp = (struct brw_fragment_program *) @@ -325,18 +317,16 @@ static void brw_upload_wm_prog( struct brw_context *brw ) /* Make an early check for the key. */ - if (brw_search_cache(&brw->cache[BRW_WM_PROG], - &key, sizeof(key), - &brw->wm.prog_data, - &brw->wm.prog_gs_offset)) - return; - - do_wm_prog(brw, fp, &key); + dri_bo_unreference(brw->wm.prog_bo); + brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG, + &key, sizeof(key), + NULL, 0, + &brw->wm.prog_data); + if (brw->wm.prog_bo == NULL) + do_wm_prog(brw, fp, &key); } -/* See brw_wm.c: - */ const struct brw_tracked_state brw_wm_prog = { .dirty = { .mesa = (_NEW_COLOR | @@ -345,12 +335,13 @@ const struct brw_tracked_state brw_wm_prog = { _NEW_POLYGON | _NEW_LINE | _NEW_LIGHT | + _NEW_BUFFERS | _NEW_TEXTURE), .brw = (BRW_NEW_FRAGMENT_PROGRAM | BRW_NEW_WM_INPUT_DIMENSIONS | BRW_NEW_REDUCED_PRIMITIVE), .cache = 0 }, - .update = brw_upload_wm_prog + .prepare = brw_prepare_wm_prog }; |