static void prepare_cc_unit( struct brw_context *brw ) { struct brw_cc_unit_key key; cc_unit_populate_key(brw, &key); dri_bo_unreference(brw->cc.state_bo); brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_CC_UNIT, &key, sizeof(key), &brw->cc.vp_bo, 1, NULL); if (brw->cc.state_bo == NULL) brw->cc.state_bo = cc_unit_create_from_key(brw, &key); }
static void upload_clip_unit( struct brw_context *brw ) { struct brw_clip_unit_key key; clip_unit_populate_key(brw, &key); dri_bo_unreference(brw->clip.state_bo); brw->clip.state_bo = brw_search_cache(&brw->cache, BRW_CLIP_UNIT, &key, sizeof(key), &brw->clip.prog_bo, 1, NULL); if (brw->clip.state_bo == NULL) { brw->clip.state_bo = clip_unit_create_from_key(brw, &key); } }
static void brw_upload_wm_prog( struct brw_context *brw ) { struct brw_wm_prog_key key; struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; brw_wm_populate_key(brw, &key); /* 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); }
static void prepare_depth_stencil_state(struct brw_context *brw) { struct brw_depth_stencil_state_key key; depth_stencil_state_populate_key(brw, &key); drm_intel_bo_unreference(brw->cc.depth_stencil_state_bo); brw->cc.depth_stencil_state_bo = brw_search_cache(&brw->cache, BRW_DEPTH_STENCIL_STATE, &key, sizeof(key), NULL, 0, NULL); if (brw->cc.depth_stencil_state_bo == NULL) brw->cc.depth_stencil_state_bo = depth_stencil_state_create_from_key(brw, &key); }
static int upload_clip_unit( struct brw_context *brw ) { struct brw_clip_unit_key key; int ret = 0; clip_unit_populate_key(brw, &key); dri_bo_unreference(brw->clip.state_bo); brw->clip.state_bo = brw_search_cache(&brw->cache, BRW_CLIP_UNIT, &key, sizeof(key), &brw->clip.prog_bo, 1, NULL); if (brw->clip.state_bo == NULL) { brw->clip.state_bo = clip_unit_create_from_key(brw, &key); } ret = dri_bufmgr_check_aperture_space(brw->clip.state_bo); return ret; }
uint32_t brw_blorp_clear_params::get_wm_prog(struct brw_context *brw, brw_blorp_prog_data **prog_data) const { uint32_t prog_offset; if (!brw_search_cache(&brw->cache, BRW_BLORP_CLEAR_PROG, &this->wm_prog_key, sizeof(this->wm_prog_key), &prog_offset, prog_data)) { brw_blorp_clear_program prog(brw, &this->wm_prog_key); GLuint program_size; const GLuint *program = prog.compile(brw, &program_size); brw_upload_cache(&brw->cache, BRW_BLORP_CLEAR_PROG, &this->wm_prog_key, sizeof(this->wm_prog_key), program, program_size, &prog.prog_data, sizeof(prog.prog_data), &prog_offset, prog_data); } return prog_offset; }
static void brw_upload_wm_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_wm_prog_key key; struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; brw_wm_populate_key(brw, &key); if (!brw_search_cache(&brw->cache, BRW_WM_PROG, &key, sizeof(key), &brw->wm.prog_offset, &brw->wm.prog_data)) { bool success = do_wm_prog(brw, ctx->Shader._CurrentFragmentProgram, fp, &key); (void) success; assert(success); } }
void brw_upload_gs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct gl_shader_program **current = ctx->_Shader->CurrentProgram; struct brw_stage_state *stage_state = &brw->gs.base; struct brw_gs_prog_key key; /* BRW_NEW_GEOMETRY_PROGRAM */ struct brw_geometry_program *gp = (struct brw_geometry_program *) brw->geometry_program; if (!brw_gs_state_dirty(brw)) return; if (gp == NULL) { /* No geometry shader. Vertex data just passes straight through. */ if (brw->gen == 6 && (brw->ctx.NewDriverState & BRW_NEW_TRANSFORM_FEEDBACK)) { gen6_brw_upload_ff_gs_prog(brw); return; } /* Other state atoms had better not try to access prog_data, since * there's no GS program. */ brw->gs.prog_data = NULL; brw->gs.base.prog_data = NULL; return; } brw_gs_populate_key(brw, &key); if (!brw_search_cache(&brw->cache, BRW_CACHE_GS_PROG, &key, sizeof(key), &stage_state->prog_offset, &brw->gs.prog_data)) { bool success = brw_codegen_gs_prog(brw, current[MESA_SHADER_GEOMETRY], gp, &key); assert(success); (void)success; } brw->gs.base.prog_data = &brw->gs.prog_data->base.base; }
static int upload_clip_unit( struct brw_context *brw ) { struct brw_clip_unit_key key; struct brw_winsys_reloc reloc[1]; unsigned grf_reg_count; enum pipe_error ret; clip_unit_populate_key(brw, &key); grf_reg_count = align(key.total_grf, 16) / 16 - 1; /* clip program relocation * * XXX: these reloc structs are long lived and only need to be * updated when the bound BO changes. Hopefully the stuff mixed in * in the delta's is non-orthogonal. */ assert(brw->clip.prog_bo); make_reloc(&reloc[0], BRW_USAGE_STATE, grf_reg_count << 1, offsetof(struct brw_clip_unit_state, thread0), brw->clip.prog_bo); if (brw_search_cache(&brw->cache, BRW_CLIP_UNIT, &key, sizeof(key), reloc, 1, NULL, &brw->clip.state_bo)) return PIPE_OK; /* Create new: */ ret = clip_unit_create_from_key(brw, &key, reloc, &brw->clip.state_bo); if (ret) return ret; return PIPE_OK; }
/* Calculate interpolants for triangle and line rasterization. */ static void prepare_gs_prog(struct brw_context *brw) { struct brw_gs_prog_key key; /* Populate the key: */ populate_key(brw, &key); if (brw->gs.prog_active != key.need_gs_prog) { brw->state.dirty.cache |= CACHE_NEW_GS_PROG; brw->gs.prog_active = key.need_gs_prog; } if (brw->gs.prog_active) { if (!brw_search_cache(&brw->cache, BRW_GS_PROG, &key, sizeof(key), &brw->gs.prog_offset, &brw->gs.prog_data)) { compile_gs_prog( brw, &key ); } } }
/* Calculate interpolants for triangle and line rasterization. */ static void brw_upload_ff_gs_prog(struct brw_context *brw) { struct brw_ff_gs_prog_key key; /* Populate the key: */ populate_key(brw, &key); if (brw->ff_gs.prog_active != key.need_gs_prog) { brw->state.dirty.brw |= BRW_NEW_FF_GS_PROG_DATA; brw->ff_gs.prog_active = key.need_gs_prog; } if (brw->ff_gs.prog_active) { if (!brw_search_cache(&brw->cache, BRW_CACHE_FF_GS_PROG, &key, sizeof(key), &brw->ff_gs.prog_offset, &brw->ff_gs.prog_data)) { compile_ff_gs_prog( brw, &key ); } } }
static void brw_upload_vs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->intel.ctx; struct brw_vs_prog_key key; struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.program_string_id = vp->id; key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled); key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); key.two_side_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide); /* _NEW_POINT */ if (ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* Make an early check for the key. */ drm_intel_bo_unreference(brw->vs.prog_bo); brw->vs.prog_bo = brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), NULL, 0, &brw->vs.prog_data); if (brw->vs.prog_bo == NULL) do_vs_prog(brw, vp, &key); brw->vs.constant_map = ((int8_t *)brw->vs.prog_data + sizeof(*brw->vs.prog_data)); }
void brw_upload_vs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct gl_shader_program **current = ctx->_Shader->CurrentProgram; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; if (!brw_vs_state_dirty(brw)) return; brw_vs_populate_key(brw, &key); if (!brw_search_cache(&brw->cache, BRW_CACHE_VS_PROG, &key, sizeof(key), &brw->vs.base.prog_offset, &brw->vs.prog_data)) { bool success = brw_codegen_vs_prog(brw, current[MESA_SHADER_VERTEX], vp, &key); (void) success; assert(success); } brw->vs.base.prog_data = &brw->vs.prog_data->base.base; if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, sizeof(brw->vue_map_geom_out)) != 0) { brw->vue_map_vs = brw->vs.prog_data->base.vue_map; brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_VS; if (brw->gen < 6) { /* No geometry shader support, so the VS VUE map is the VUE map for * the output of the "geometry" portion of the pipeline. */ brw->vue_map_geom_out = brw->vue_map_vs; brw->ctx.NewDriverState |= BRW_NEW_VUE_MAP_GEOM_OUT; } } }
static void brw_update_texture_surface( GLcontext *ctx, GLuint unit ) { struct brw_context *brw = brw_context(ctx); struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel]; struct brw_surface_key key; const GLuint surf = SURF_INDEX_TEXTURE(unit); memset(&key, 0, sizeof(key)); key.format = firstImage->TexFormat; key.internal_format = firstImage->InternalFormat; key.pitch = intelObj->mt->pitch; key.depth = firstImage->Depth; key.bo = intelObj->mt->region->buffer; key.offset = 0; key.target = tObj->Target; key.depthmode = tObj->DepthMode; key.first_level = intelObj->firstLevel; key.last_level = intelObj->lastLevel; key.width = firstImage->Width; key.height = firstImage->Height; key.cpp = intelObj->mt->cpp; key.tiling = intelObj->mt->region->tiling; dri_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, 1, NULL); if (brw->wm.surf_bo[surf] == NULL) { brw->wm.surf_bo[surf] = brw_create_texture_surface(brw, &key); } }
void brw_upload_wm_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct gl_shader_program *current = ctx->_Shader->_CurrentFragmentProgram; struct brw_wm_prog_key key; struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; if (!brw_wm_state_dirty(brw)) return; brw_wm_populate_key(brw, &key); if (!brw_search_cache(&brw->cache, BRW_CACHE_FS_PROG, &key, sizeof(key), &brw->wm.base.prog_offset, &brw->wm.prog_data)) { bool success = brw_codegen_wm_prog(brw, current, fp, &key); (void) success; assert(success); } brw->wm.base.prog_data = &brw->wm.prog_data->base; }
static enum pipe_error brw_prepare_wm_prog(struct brw_context *brw) { struct brw_wm_prog_key key; struct brw_fragment_shader *fs = brw->curr.fragment_shader; enum pipe_error ret; brw_wm_populate_key(brw, &key); /* Make an early check for the key. */ if (brw_search_cache(&brw->cache, BRW_WM_PROG, &key, sizeof(key), NULL, 0, &brw->wm.prog_data, &brw->wm.prog_bo)) return PIPE_OK; ret = do_wm_prog(brw, fs, &key, &brw->wm.prog_bo); if (ret) return ret; return PIPE_OK; }
/* Calculate interpolants for triangle and line rasterization. */ void brw_upload_clip_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_clip_prog_key key; if (!brw_state_dirty(brw, _NEW_BUFFERS | _NEW_LIGHT | _NEW_POLYGON | _NEW_TRANSFORM, BRW_NEW_BLORP | BRW_NEW_FS_PROG_DATA | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT)) return; memset(&key, 0, sizeof(key)); /* Populate the key: */ /* BRW_NEW_FS_PROG_DATA */ const struct brw_wm_prog_data *wm_prog_data = brw_wm_prog_data(brw->wm.base.prog_data); if (wm_prog_data) { key.contains_flat_varying = wm_prog_data->contains_flat_varying; key.contains_noperspective_varying = wm_prog_data->contains_noperspective_varying; STATIC_ASSERT(sizeof(key.interp_mode) == sizeof(wm_prog_data->interp_mode)); memcpy(key.interp_mode, wm_prog_data->interp_mode, sizeof(key.interp_mode)); } /* BRW_NEW_REDUCED_PRIMITIVE */ key.primitive = brw->reduced_primitive; /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* _NEW_LIGHT */ key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); /* _NEW_TRANSFORM (also part of VUE map)*/ if (ctx->Transform.ClipPlanesEnabled) key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; if (brw->gen == 5) key.clip_mode = BRW_CLIP_MODE_KERNEL_CLIP; else key.clip_mode = BRW_CLIP_MODE_NORMAL; /* _NEW_POLYGON */ if (key.primitive == GL_TRIANGLES) { if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) key.clip_mode = BRW_CLIP_MODE_REJECT_ALL; else { GLuint fill_front = BRW_CLIP_FILL_MODE_CULL; GLuint fill_back = BRW_CLIP_FILL_MODE_CULL; GLuint offset_front = 0; GLuint offset_back = 0; if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_FRONT) { switch (ctx->Polygon.FrontMode) { case GL_FILL: fill_front = BRW_CLIP_FILL_MODE_FILL; offset_front = 0; break; case GL_LINE: fill_front = BRW_CLIP_FILL_MODE_LINE; offset_front = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_front = BRW_CLIP_FILL_MODE_POINT; offset_front = ctx->Polygon.OffsetPoint; break; } } if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_BACK) { switch (ctx->Polygon.BackMode) { case GL_FILL: fill_back = BRW_CLIP_FILL_MODE_FILL; offset_back = 0; break; case GL_LINE: fill_back = BRW_CLIP_FILL_MODE_LINE; offset_back = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_back = BRW_CLIP_FILL_MODE_POINT; offset_back = ctx->Polygon.OffsetPoint; break; } } if (ctx->Polygon.BackMode != GL_FILL || ctx->Polygon.FrontMode != GL_FILL) { key.do_unfilled = 1; /* Most cases the fixed function units will handle. Cases where * one or more polygon faces are unfilled will require help: */ key.clip_mode = BRW_CLIP_MODE_CLIP_NON_REJECTED; if (offset_back || offset_front) { /* _NEW_POLYGON, _NEW_BUFFERS */ key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2; key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD; key.offset_clamp = ctx->Polygon.OffsetClamp * ctx->DrawBuffer->_MRD; } if (!brw->polygon_front_bit) { key.fill_ccw = fill_front; key.fill_cw = fill_back; key.offset_ccw = offset_front; key.offset_cw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_cw != BRW_CLIP_FILL_MODE_CULL) key.copy_bfc_cw = 1; } else { key.fill_cw = fill_front; key.fill_ccw = fill_back; key.offset_cw = offset_front; key.offset_ccw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) key.copy_bfc_ccw = 1; } } } } if (!brw_search_cache(&brw->cache, BRW_CACHE_CLIP_PROG, &key, sizeof(key), &brw->clip.prog_offset, &brw->clip.prog_data)) { compile_clip_prog( brw, &key ); } }
/* Calculate interpolants for triangle and line rasterization. */ static void brw_upload_sf_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_sf_prog_key key; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); memset(&key, 0, sizeof(key)); /* Populate the key, noting state dependencies: */ /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* BRW_NEW_REDUCED_PRIMITIVE */ switch (brw->reduced_primitive) { case GL_TRIANGLES: /* NOTE: We just use the edgeflag attribute as an indicator that * unfilled triangles are active. We don't actually do the * edgeflag testing here, it is already done in the clip * program. */ if (key.attrs & BITFIELD64_BIT(VARYING_SLOT_EDGE)) key.primitive = SF_UNFILLED_TRIS; else key.primitive = SF_TRIANGLES; break; case GL_LINES: key.primitive = SF_LINES; break; case GL_POINTS: key.primitive = SF_POINTS; break; } /* _NEW_TRANSFORM */ key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); /* _NEW_POINT */ key.do_point_sprite = ctx->Point.PointSprite; if (key.do_point_sprite) { int i; for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_sprite_coord_replace |= (1 << i); } } if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(VARYING_SLOT_PNTC)) key.do_point_coord = 1; /* * Window coordinates in a FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) key.sprite_origin_lower_left = true; /* BRW_NEW_INTERPOLATION_MAP */ key.interpolation_mode = brw->interpolation_mode; /* _NEW_LIGHT | _NEW_PROGRAM */ key.do_twoside_color = ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) || ctx->VertexProgram._TwoSideEnabled); /* _NEW_POLYGON */ if (key.do_twoside_color) { /* If we're rendering to a FBO, we have to invert the polygon * face orientation, just as we invert the viewport in * sf_unit_create_from_key(). */ key.frontface_ccw = (ctx->Polygon.FrontFace == GL_CCW) != render_to_fbo; } if (!brw_search_cache(&brw->cache, BRW_SF_PROG, &key, sizeof(key), &brw->sf.prog_offset, &brw->sf.prog_data)) { compile_sf_prog( brw, &key ); } }
static void brw_upload_gs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_stage_state *stage_state = &brw->gs.base; struct brw_gs_prog_key key; /* BRW_NEW_GEOMETRY_PROGRAM */ struct brw_geometry_program *gp = (struct brw_geometry_program *) brw->geometry_program; if (gp == NULL) { /* No geometry shader. Vertex data just passes straight through. */ if (brw->state.dirty.brw & BRW_NEW_VUE_MAP_VS) { brw->vue_map_geom_out = brw->vue_map_vs; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } if (brw->gen == 6 && (brw->state.dirty.brw & BRW_NEW_TRANSFORM_FEEDBACK)) { gen6_brw_upload_ff_gs_prog(brw); return; } /* Other state atoms had better not try to access prog_data, since * there's no GS program. */ brw->gs.prog_data = NULL; brw->gs.base.prog_data = NULL; return; } struct gl_program *prog = &gp->program.Base; memset(&key, 0, sizeof(key)); key.base.program_string_id = gp->id; brw_setup_vec4_key_clip_info(brw, &key.base, gp->program.Base.UsesClipDistanceOut); /* _NEW_LIGHT | _NEW_BUFFERS */ key.base.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count, &key.base.tex); /* BRW_NEW_VUE_MAP_VS */ key.input_varyings = brw->vue_map_vs.slots_valid; if (!brw_search_cache(&brw->cache, BRW_GS_PROG, &key, sizeof(key), &stage_state->prog_offset, &brw->gs.prog_data)) { bool success = do_gs_prog(brw, ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY], gp, &key); assert(success); (void)success; } brw->gs.base.prog_data = &brw->gs.prog_data->base.base; if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, sizeof(brw->vue_map_geom_out)) != 0) { brw->vue_map_geom_out = brw->gs.prog_data->base.vue_map; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } }
static void brw_upload_vs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.base.program_string_id = vp->id; key.base.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); key.base.uses_clip_distance = vp->program.UsesClipDistance; if (key.base.userclip_active && !key.base.uses_clip_distance) { if (brw->gen < 6) { key.base.nr_userclip_plane_consts = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); key.base.userclip_planes_enabled_gen_4_5 = ctx->Transform.ClipPlanesEnabled; } else { key.base.nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } } /* _NEW_POLYGON */ if (brw->gen < 6) { key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } /* _NEW_LIGHT | _NEW_BUFFERS */ key.base.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POINT */ if (brw->gen < 6 && ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key.base.tex); /* BRW_NEW_VERTICES */ if (brw->gen < 8 && !brw->is_haswell) { /* Prior to Haswell, the hardware can't natively support GL_FIXED or * 2_10_10_10_REV vertex formats. Set appropriate workaround flags. */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (!(vp->program.Base.InputsRead & BITFIELD64_BIT(i))) continue; uint8_t wa_flags = 0; switch (brw->vb.inputs[i].glarray->Type) { case GL_FIXED: wa_flags = brw->vb.inputs[i].glarray->Size; break; case GL_INT_2_10_10_10_REV: wa_flags |= BRW_ATTRIB_WA_SIGN; /* fallthough */ case GL_UNSIGNED_INT_2_10_10_10_REV: if (brw->vb.inputs[i].glarray->Format == GL_BGRA) wa_flags |= BRW_ATTRIB_WA_BGRA; if (brw->vb.inputs[i].glarray->Normalized) wa_flags |= BRW_ATTRIB_WA_NORMALIZE; else if (!brw->vb.inputs[i].glarray->Integer) wa_flags |= BRW_ATTRIB_WA_SCALE; break; } key.gl_attrib_wa_flags[i] = wa_flags; } } if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.prog_offset, &brw->vs.prog_data)) { bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, vp, &key); assert(success); } if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, sizeof(brw->vue_map_geom_out)) != 0) { brw->vue_map_geom_out = brw->vs.prog_data->base.vue_map; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } }
/* Calculate interpolants for triangle and line rasterization. */ static void brw_upload_clip_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_clip_prog_key key; memset(&key, 0, sizeof(key)); /* Populate the key: */ /* BRW_NEW_INTERPOLATION_MAP */ key.interpolation_mode = brw->interpolation_mode; /* BRW_NEW_REDUCED_PRIMITIVE */ key.primitive = brw->reduced_primitive; /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* _NEW_LIGHT */ key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); /* _NEW_TRANSFORM (also part of VUE map)*/ key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); if (brw->gen == 5) key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP; else key.clip_mode = BRW_CLIPMODE_NORMAL; /* _NEW_POLYGON */ if (key.primitive == GL_TRIANGLES) { if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) key.clip_mode = BRW_CLIPMODE_REJECT_ALL; else { GLuint fill_front = CLIP_CULL; GLuint fill_back = CLIP_CULL; GLuint offset_front = 0; GLuint offset_back = 0; if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_FRONT) { switch (ctx->Polygon.FrontMode) { case GL_FILL: fill_front = CLIP_FILL; offset_front = 0; break; case GL_LINE: fill_front = CLIP_LINE; offset_front = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_front = CLIP_POINT; offset_front = ctx->Polygon.OffsetPoint; break; } } if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_BACK) { switch (ctx->Polygon.BackMode) { case GL_FILL: fill_back = CLIP_FILL; offset_back = 0; break; case GL_LINE: fill_back = CLIP_LINE; offset_back = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_back = CLIP_POINT; offset_back = ctx->Polygon.OffsetPoint; break; } } if (ctx->Polygon.BackMode != GL_FILL || ctx->Polygon.FrontMode != GL_FILL) { key.do_unfilled = 1; /* Most cases the fixed function units will handle. Cases where * one or more polygon faces are unfilled will require help: */ key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED; if (offset_back || offset_front) { /* _NEW_POLYGON, _NEW_BUFFERS */ key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2; key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD; } switch (ctx->Polygon.FrontFace) { case GL_CCW: key.fill_ccw = fill_front; key.fill_cw = fill_back; key.offset_ccw = offset_front; key.offset_cw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_cw != CLIP_CULL) key.copy_bfc_cw = 1; break; case GL_CW: key.fill_cw = fill_front; key.fill_ccw = fill_back; key.offset_cw = offset_front; key.offset_ccw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_ccw != CLIP_CULL) key.copy_bfc_ccw = 1; break; } } } } if (!brw_search_cache(&brw->cache, BRW_CLIP_PROG, &key, sizeof(key), &brw->clip.prog_offset, &brw->clip.prog_data)) { compile_clip_prog( brw, &key ); } }
/** * 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 intel_context *intel = &brw->intel; GLcontext *ctx = &intel->ctx; dri_bo *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_x; uint32_t draw_y; } key; memset(&key, 0, sizeof(key)); if (region != NULL) { region_bo = region->buffer; key.surface_type = BRW_SURFACE_2D; switch (irb->Base.Format) { /* XRGB and ARGB are treated the same here because the chips in this * family cannot render to XRGB targets. This means that we have to * mask writes to alpha (ala glColorMask) and reconfigure the alpha * blending hardware to use GL_ONE (or GL_ZERO) for cases where * GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is used. */ case MESA_FORMAT_ARGB8888: case MESA_FORMAT_XRGB8888: key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; break; case MESA_FORMAT_RGB565: key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; break; case MESA_FORMAT_ARGB1555: key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM; break; case MESA_FORMAT_ARGB4444: key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; break; default: _mesa_problem(ctx, "Bad renderbuffer format: %d\n", irb->Base.Format); } 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_x = region->draw_x; key.draw_y = region->draw_y; } 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_x = 0; key.draw_y = 0; } if (intel->gen < 6) { /* _NEW_COLOR */ memcpy(key.color_mask, ctx->Color.ColorMask[unit], sizeof(key.color_mask)); /* As mentioned above, disable writes to the alpha component when the * renderbuffer is XRGB. */ if (ctx->DrawBuffer->Visual.alphaBits == 0) key.color_mask[3] = GL_FALSE; key.color_blend = (!ctx->Color._LogicOpEnabled && (ctx->Color.BlendEnabled & (1 << unit))); } dri_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_x + key.draw_y * key.pitch) * key.cpp; } else { uint32_t tile_base, tile_x, tile_y; uint32_t pitch = key.pitch * key.cpp; if (key.tiling == I915_TILING_X) { tile_x = key.draw_x % (512 / key.cpp); tile_y = key.draw_y % 8; tile_base = ((key.draw_y / 8) * (8 * pitch)); tile_base += (key.draw_x - tile_x) / (512 / key.cpp) * 4096; } else { /* Y */ tile_x = key.draw_x % (128 / key.cpp); tile_y = key.draw_y % 32; tile_base = ((key.draw_y / 32) * (32 * pitch)); tile_base += (key.draw_x - tile_x) / (128 / key.cpp) * 4096; } assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0)); assert(tile_x % 4 == 0); assert(tile_y % 2 == 0); /* Note that the low bits of these fields are missing, so * there's the possibility of getting in trouble. */ surf.ss1.base_addr = tile_base; surf.ss5.x_offset = tile_x / 4; surf.ss5.y_offset = tile_y / 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; if (intel->gen < 6) { /* _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)); 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); } }
/* Calculate interpolants for triangle and line rasterization. */ static void upload_clip_prog(struct brw_context *brw) { struct intel_context *intel = &brw->intel; GLcontext *ctx = &intel->ctx; struct brw_clip_prog_key key; memset(&key, 0, sizeof(key)); /* Populate the key: */ /* BRW_NEW_REDUCED_PRIMITIVE */ key.primitive = brw->intel.reduced_primitive; /* CACHE_NEW_VS_PROG */ key.attrs = brw->vs.prog_data->outputs_written; /* _NEW_LIGHT */ key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT); key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); /* _NEW_TRANSFORM */ key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled); if (intel->gen == 5) key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP; else key.clip_mode = BRW_CLIPMODE_NORMAL; /* _NEW_POLYGON */ if (key.primitive == GL_TRIANGLES) { if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) key.clip_mode = BRW_CLIPMODE_REJECT_ALL; else { GLuint fill_front = CLIP_CULL; GLuint fill_back = CLIP_CULL; GLuint offset_front = 0; GLuint offset_back = 0; if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_FRONT) { switch (ctx->Polygon.FrontMode) { case GL_FILL: fill_front = CLIP_FILL; offset_front = 0; break; case GL_LINE: fill_front = CLIP_LINE; offset_front = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_front = CLIP_POINT; offset_front = ctx->Polygon.OffsetPoint; break; } } if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_BACK) { switch (ctx->Polygon.BackMode) { case GL_FILL: fill_back = CLIP_FILL; offset_back = 0; break; case GL_LINE: fill_back = CLIP_LINE; offset_back = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_back = CLIP_POINT; offset_back = ctx->Polygon.OffsetPoint; break; } } if (ctx->Polygon.BackMode != GL_FILL || ctx->Polygon.FrontMode != GL_FILL) { key.do_unfilled = 1; /* Most cases the fixed function units will handle. Cases where * one or more polygon faces are unfilled will require help: */ key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED; if (offset_back || offset_front) { /* _NEW_POLYGON, _NEW_BUFFERS */ key.offset_units = ctx->Polygon.OffsetUnits * brw->intel.polygon_offset_scale; key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD; } switch (ctx->Polygon.FrontFace) { case GL_CCW: key.fill_ccw = fill_front; key.fill_cw = fill_back; key.offset_ccw = offset_front; key.offset_cw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_cw != CLIP_CULL) key.copy_bfc_cw = 1; break; case GL_CW: key.fill_cw = fill_front; key.fill_ccw = fill_back; key.offset_cw = offset_front; key.offset_ccw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_ccw != CLIP_CULL) key.copy_bfc_ccw = 1; break; } } } } drm_intel_bo_unreference(brw->clip.prog_bo); brw->clip.prog_bo = brw_search_cache(&brw->cache, BRW_CLIP_PROG, &key, sizeof(key), NULL, 0, &brw->clip.prog_data); if (brw->clip.prog_bo == NULL) compile_clip_prog( brw, &key ); }
/* Calculate interpolants for triangle and line rasterization. */ void brw_upload_sf_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_sf_prog_key key; if (!brw_state_dirty(brw, _NEW_BUFFERS | _NEW_HINT | _NEW_LIGHT | _NEW_POINT | _NEW_POLYGON | _NEW_PROGRAM | _NEW_TRANSFORM, BRW_NEW_BLORP | BRW_NEW_FS_PROG_DATA | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT)) return; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); memset(&key, 0, sizeof(key)); /* Populate the key, noting state dependencies: */ /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* BRW_NEW_REDUCED_PRIMITIVE */ switch (brw->reduced_primitive) { case GL_TRIANGLES: /* NOTE: We just use the edgeflag attribute as an indicator that * unfilled triangles are active. We don't actually do the * edgeflag testing here, it is already done in the clip * program. */ if (key.attrs & BITFIELD64_BIT(VARYING_SLOT_EDGE)) key.primitive = BRW_SF_PRIM_UNFILLED_TRIS; else key.primitive = BRW_SF_PRIM_TRIANGLES; break; case GL_LINES: key.primitive = BRW_SF_PRIM_LINES; break; case GL_POINTS: key.primitive = BRW_SF_PRIM_POINTS; break; } /* _NEW_TRANSFORM */ key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); /* _NEW_POINT */ key.do_point_sprite = ctx->Point.PointSprite; if (key.do_point_sprite) { key.point_sprite_coord_replace = ctx->Point.CoordReplace & 0xff; } if (brw->programs[MESA_SHADER_FRAGMENT]->info.inputs_read & BITFIELD64_BIT(VARYING_SLOT_PNTC)) { key.do_point_coord = 1; } /* * Window coordinates in a FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) key.sprite_origin_lower_left = true; /* BRW_NEW_FS_PROG_DATA */ const struct brw_wm_prog_data *wm_prog_data = brw_wm_prog_data(brw->wm.base.prog_data); if (wm_prog_data) { key.contains_flat_varying = wm_prog_data->contains_flat_varying; STATIC_ASSERT(sizeof(key.interp_mode) == sizeof(wm_prog_data->interp_mode)); memcpy(key.interp_mode, wm_prog_data->interp_mode, sizeof(key.interp_mode)); } /* _NEW_LIGHT | _NEW_PROGRAM */ key.do_twoside_color = _mesa_vertex_program_two_side_enabled(ctx); /* _NEW_POLYGON */ if (key.do_twoside_color) { /* If we're rendering to a FBO, we have to invert the polygon * face orientation, just as we invert the viewport in * sf_unit_create_from_key(). */ key.frontface_ccw = brw->polygon_front_bit == render_to_fbo; } if (!brw_search_cache(&brw->cache, BRW_CACHE_SF_PROG, &key, sizeof(key), &brw->sf.prog_offset, &brw->sf.prog_data)) { compile_sf_prog( brw, &key ); } }
static void brw_upload_vs_prog(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.program_string_id = vp->id; key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); key.uses_clip_distance = vp->program.UsesClipDistance; if (key.userclip_active && !key.uses_clip_distance) { if (intel->gen < 6) { key.nr_userclip_plane_consts = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); key.userclip_planes_enabled_gen_4_5 = ctx->Transform.ClipPlanesEnabled; } else { key.nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } } /* _NEW_POLYGON */ if (intel->gen < 6) { key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } /* _NEW_LIGHT | _NEW_BUFFERS */ key.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POINT */ if (ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key.tex); /* BRW_NEW_VERTICES */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (vp->program.Base.InputsRead & BITFIELD64_BIT(i) && brw->vb.inputs[i].glarray->Type == GL_FIXED) { key.gl_fixed_input_size[i] = brw->vb.inputs[i].glarray->Size; } } if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.prog_offset, &brw->vs.prog_data)) { bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, vp, &key); assert(success); } brw->vs.constant_map = ((int8_t *)brw->vs.prog_data + sizeof(*brw->vs.prog_data)); }