static void upload_clip_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t dw2 = 0; /* _NEW_BUFFERS */ struct gl_framebuffer *fb = ctx->DrawBuffer; /* CACHE_NEW_WM_PROG */ if (brw->wm.prog_data->barycentric_interp_modes & BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) { dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; } if (!ctx->Transform.DepthClamp) dw2 |= GEN6_CLIP_Z_TEST; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { dw2 |= (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } else { dw2 |= (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } /* _NEW_TRANSFORM */ dw2 |= (ctx->Transform.ClipPlanesEnabled << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT); if (ctx->Viewport.X == 0 && ctx->Viewport.Y == 0 && ctx->Viewport.Width == fb->Width && ctx->Viewport.Height == fb->Height) { dw2 |= GEN6_CLIP_GB_TEST; } BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(GEN6_CLIP_STATISTICS_ENABLE); OUT_BATCH(GEN6_CLIP_ENABLE | GEN6_CLIP_API_OGL | GEN6_CLIP_MODE_NORMAL | GEN6_CLIP_XY_TEST | dw2); OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | GEN6_CLIP_FORCE_ZERO_RTAINDEX); ADVANCE_BATCH(); }
/** * SAMPLER_STATE. See gen7_update_sampler_state(). */ static uint32_t gen7_blorp_emit_sampler_state(struct brw_context *brw, const brw_blorp_params *params) { uint32_t sampler_offset; struct gen7_sampler_state *sampler = (struct gen7_sampler_state *) brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE, sizeof(struct gen7_sampler_state), 32, &sampler_offset); memset(sampler, 0, sizeof(*sampler)); sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; // sampler->ss0.min_mag_neq = 1; /* Set LOD bias: */ sampler->ss0.lod_bias = 0; sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ /* Set BaseMipLevel, MaxLOD, MinLOD: * * XXX: I don't think that using firstLevel, lastLevel works, * because we always setup the surface state as if firstLevel == * level zero. Probably have to subtract firstLevel from each of * these: */ sampler->ss0.base_level = U_FIXED(0, 1); sampler->ss1.max_lod = U_FIXED(0, 8); sampler->ss1.min_lod = U_FIXED(0, 8); sampler->ss3.non_normalized_coord = 1; sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; return sampler_offset; }
static void upload_clip_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t depth_clamp = 0; uint32_t provoking, userclip; uint32_t nonperspective_barycentric_enable_flag = 0; /* CACHE_NEW_WM_PROG */ if (brw->wm.prog_data->barycentric_interp_modes & BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) { nonperspective_barycentric_enable_flag = GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; } if (!ctx->Transform.DepthClamp) depth_clamp = GEN6_CLIP_Z_TEST; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { provoking = (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } else { provoking = (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } /* _NEW_TRANSFORM */ userclip = ctx->Transform.ClipPlanesEnabled; BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(GEN6_CLIP_STATISTICS_ENABLE); OUT_BATCH(GEN6_CLIP_ENABLE | GEN6_CLIP_API_OGL | GEN6_CLIP_MODE_NORMAL | nonperspective_barycentric_enable_flag | GEN6_CLIP_XY_TEST | GEN6_CLIP_GB_TEST | userclip << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT | depth_clamp | provoking); OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | GEN6_CLIP_FORCE_ZERO_RTAINDEX); ADVANCE_BATCH(); }
static void upload_sf(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; uint32_t dw1 = 0, dw2 = 0, dw3 = 0; float point_size; dw1 = GEN6_SF_STATISTICS_ENABLE; if (brw->sf.viewport_transform_enable) dw1 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; /* _NEW_LINE */ uint32_t line_width_u3_7 = brw_get_line_width(brw); if (brw->gen >= 9 || brw->is_cherryview) { dw1 |= line_width_u3_7 << GEN9_SF_LINE_WIDTH_SHIFT; } else { dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } /* _NEW_POINT - Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw3 |= U_FIXED(CLAMP(point_size, 0.125f, 255.875f), 3); /* _NEW_PROGRAM | _NEW_POINT, BRW_NEW_VUE_MAP_GEOM_OUT */ if (use_state_point_size(brw)) dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* _NEW_POINT | _NEW_MULTISAMPLE */ if ((ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) && !ctx->Point.PointSprite) { dw3 |= GEN8_SF_SMOOTH_POINT_ENABLE; } dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_SF << 16 | (4 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); ADVANCE_BATCH(); }
static void upload_clip_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t depth_clamp = 0; uint32_t provoking, userclip; if (!ctx->Transform.DepthClamp) depth_clamp = GEN6_CLIP_Z_TEST; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { provoking = (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } else { provoking = (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } /* _NEW_TRANSFORM */ userclip = (1 << brw_count_bits(ctx->Transform.ClipPlanesEnabled)) - 1; BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(GEN6_CLIP_STATISTICS_ENABLE); OUT_BATCH(GEN6_CLIP_ENABLE | GEN6_CLIP_API_OGL | GEN6_CLIP_MODE_NORMAL | GEN6_CLIP_XY_TEST | userclip << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT | depth_clamp | provoking); OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | GEN6_CLIP_FORCE_ZERO_RTAINDEX); ADVANCE_BATCH(); }
static void upload_clip_state(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_META_IN_PROGRESS */ uint32_t dw1 = brw->meta_in_progress ? 0 : GEN6_CLIP_STATISTICS_ENABLE; uint32_t dw2 = 0; /* _NEW_BUFFERS */ struct gl_framebuffer *fb = ctx->DrawBuffer; /* BRW_NEW_FS_PROG_DATA */ if (brw->wm.prog_data->barycentric_interp_modes & BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) { dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; } dw1 |= brw->vs.prog_data->base.cull_distance_mask; if (brw->gen >= 7) dw1 |= GEN7_CLIP_EARLY_CULL; if (brw->gen == 7) { /* _NEW_POLYGON */ if (ctx->Polygon._FrontBit == _mesa_is_user_fbo(fb)) dw1 |= GEN7_CLIP_WINDING_CCW; if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw1 |= GEN7_CLIP_CULLMODE_FRONT; break; case GL_BACK: dw1 |= GEN7_CLIP_CULLMODE_BACK; break; case GL_FRONT_AND_BACK: dw1 |= GEN7_CLIP_CULLMODE_BOTH; break; default: unreachable("Should not get here: invalid CullFlag"); } } else { dw1 |= GEN7_CLIP_CULLMODE_NONE; } } if (brw->gen < 8 && !ctx->Transform.DepthClamp) dw2 |= GEN6_CLIP_Z_TEST; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { dw2 |= (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } else { dw2 |= (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } /* _NEW_TRANSFORM */ dw2 |= (ctx->Transform.ClipPlanesEnabled << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT); if (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE) dw2 |= GEN6_CLIP_API_D3D; else dw2 |= GEN6_CLIP_API_OGL; dw2 |= GEN6_CLIP_GB_TEST; /* We need to disable guardband clipping if the guardband (which we always * program to the maximum screen-space bounding box of 8K x 8K) will be * smaller than the viewport. * * Closely examining the clip determination formulas in the documentation * reveals that objects will be discarded entirely if they're outside the * (small) guardband, even if they're within the (large) viewport: * * TR = TR_GB || TR_VPXY || TR_VPZ || TR_UC || TR_NEGW * TA = !TR && TA_GB && TA_VPZ && TA_NEGW * MC = !(TA || TR) * * (TA is "Trivial Accept", TR is "Trivial Reject", MC is "Must Clip".) * * Disabling guardband clipping removes the TR_GB condition, which means * they'll be considered MC ("Must Clip") unless they're rejected for * some other reason. * * Note that there is no TA_VPXY condition. If there were, objects entirely * inside a 16384x16384 viewport would be trivially accepted, breaking the * "objects must have a screenspace bounding box not exceeding 8K in the X * or Y direction" restriction. Instead, they're clipped. */ for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) { if (ctx->ViewportArray[i].Width > 8192 || ctx->ViewportArray[i].Height > 8192) { dw2 &= ~GEN6_CLIP_GB_TEST; break; } } /* If the viewport dimensions are smaller than the drawable dimensions, * we have to disable guardband clipping prior to Gen8. We always program * the guardband to a fixed size, which is almost always larger than the * viewport. Any geometry which intersects the viewport but lies within * the guardband would bypass the 3D clipping stage, so it wouldn't be * clipped to the viewport. Rendering would happen beyond the viewport, * but still inside the drawable. * * Gen8+ introduces a viewport extents test which restricts rendering to * the viewport, so we can ignore this restriction. */ if (brw->gen < 8) { const float fb_width = (float)_mesa_geometric_width(fb); const float fb_height = (float)_mesa_geometric_height(fb); for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) { if (ctx->ViewportArray[i].X != 0 || ctx->ViewportArray[i].Y != 0 || ctx->ViewportArray[i].Width != fb_width || ctx->ViewportArray[i].Height != fb_height) { dw2 &= ~GEN6_CLIP_GB_TEST; break; } } } /* BRW_NEW_RASTERIZER_DISCARD */ if (ctx->RasterDiscard) { dw2 |= GEN6_CLIP_MODE_REJECT_ALL; if (brw->gen == 6) { perf_debug("Rasterizer discard is currently implemented via the " "clipper; having the GS not write primitives would " "likely be faster.\n"); } } uint32_t enable; if (brw->primitive == _3DPRIM_RECTLIST) enable = 0; else enable = GEN6_CLIP_ENABLE; if (!is_drawing_points(brw) && !is_drawing_lines(brw)) dw2 |= GEN6_CLIP_XY_TEST; /* BRW_NEW_VUE_MAP_GEOM_OUT */ const int max_vp_index = (brw->vue_map_geom_out.slots_valid & VARYING_BIT_VIEWPORT) != 0 ? ctx->Const.MaxViewports : 1; BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(dw1); OUT_BATCH(enable | GEN6_CLIP_MODE_NORMAL | dw2); OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | (_mesa_geometric_layers(fb) > 0 ? 0 : GEN6_CLIP_FORCE_ZERO_RTAINDEX) | ((max_vp_index - 1) & GEN6_CLIP_MAX_VP_INDEX_MASK)); ADVANCE_BATCH(); }
static void upload_sf_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t urb_entry_read_length; /* BRW_NEW_FRAGMENT_PROGRAM */ uint32_t num_outputs = _mesa_bitcount_64(brw->fragment_program->Base.InputsRead); /* _NEW_LIGHT */ bool shade_model_flat = ctx->Light.ShadeModel == GL_FLAT; uint32_t dw1, dw2, dw3, dw4, dw16, dw17; int i; /* _NEW_BUFFER */ bool render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0; int attr = 0, input_index = 0; int urb_entry_read_offset = 1; float point_size; uint16_t attr_overrides[FRAG_ATTRIB_MAX]; uint32_t point_sprite_origin; /* CACHE_NEW_VS_PROG */ urb_entry_read_length = ((brw->vs.prog_data->vue_map.num_slots + 1) / 2 - urb_entry_read_offset); if (urb_entry_read_length == 0) { /* Setting the URB entry read length to 0 causes undefined behavior, so * if we have no URB data to read, set it to 1. */ urb_entry_read_length = 1; } dw1 = GEN6_SF_SWIZZLE_ENABLE | num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT | urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT; dw2 = GEN6_SF_STATISTICS_ENABLE | GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; dw3 = 0; dw4 = 0; dw16 = 0; dw17 = 0; /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw2 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw2 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw2 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw2 |= GEN6_SF_FRONT_POINT; break; default: assert(0); break; } switch (ctx->Polygon.BackMode) { case GL_FILL: dw2 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw2 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw2 |= GEN6_SF_BACK_POINT; break; default: assert(0); break; } /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) dw3 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_POLYGON */ if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw3 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw3 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw3 |= GEN6_SF_CULL_BOTH; break; default: assert(0); break; } } else { dw3 |= GEN6_SF_CULL_NONE; } /* _NEW_LINE */ dw3 |= U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7) << GEN6_SF_LINE_WIDTH_SHIFT; if (ctx->Line.SmoothFlag) { dw3 |= GEN6_SF_LINE_AA_ENABLE; dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; dw3 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw4 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); /* * Window coordinates in an FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) { point_sprite_origin = GEN6_SF_POINT_SPRITE_LOWERLEFT; } else { point_sprite_origin = GEN6_SF_POINT_SPRITE_UPPERLEFT; } dw1 |= point_sprite_origin; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw4 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw4 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } /* Create the mapping from the FS inputs we produce to the VS outputs * they source from. */ for (; attr < FRAG_ATTRIB_MAX; attr++) { enum glsl_interp_qualifier interp_qualifier = brw->fragment_program->InterpQualifier[attr]; bool is_gl_Color = attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1; if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) continue; /* _NEW_POINT */ if (ctx->Point.PointSprite && (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) && ctx->Point.CoordReplace[attr - FRAG_ATTRIB_TEX0]) { dw16 |= (1 << input_index); } if (attr == FRAG_ATTRIB_PNTC) dw16 |= (1 << input_index); /* flat shading */ if (interp_qualifier == INTERP_QUALIFIER_FLAT || (shade_model_flat && is_gl_Color && interp_qualifier == INTERP_QUALIFIER_NONE)) dw17 |= (1 << input_index); /* The hardware can only do the overrides on 16 overrides at a * time, and the other up to 16 have to be lined up so that the * input index = the output index. We'll need to do some * tweaking to make sure that's the case. */ assert(input_index < 16 || attr == input_index); /* CACHE_NEW_VS_PROG | _NEW_LIGHT | _NEW_PROGRAM */ attr_overrides[input_index++] = get_attr_override(&brw->vs.prog_data->vue_map, urb_entry_read_offset, attr, ctx->VertexProgram._TwoSideEnabled); } for (; input_index < FRAG_ATTRIB_MAX; input_index++) attr_overrides[input_index] = 0; BEGIN_BATCH(20); OUT_BATCH(_3DSTATE_SF << 16 | (20 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH(dw4); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ for (i = 0; i < 8; i++) { OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16); } OUT_BATCH(dw16); /* point sprite texcoord bitmask */ OUT_BATCH(dw17); /* constant interp bitmask */ OUT_BATCH(0); /* wrapshortest enables 0-7 */ OUT_BATCH(0); /* wrapshortest enables 8-15 */ ADVANCE_BATCH(); }
static void upload_sf_state(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; uint32_t dw1, dw2, dw3; float point_size; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); const bool multisampled_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1; dw1 = GEN6_SF_STATISTICS_ENABLE; if (brw->sf.viewport_transform_enable) dw1 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; /* _NEW_BUFFERS */ dw1 |= (brw_depthbuffer_format(brw) << GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); /* _NEW_POLYGON */ if (ctx->Polygon._FrontBit == render_to_fbo) dw1 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw1 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_FRONT_POINT; break; default: unreachable("not reached"); } switch (ctx->Polygon.BackMode) { case GL_FILL: dw1 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_BACK_POINT; break; default: unreachable("not reached"); } dw2 = 0; if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw2 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw2 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw2 |= GEN6_SF_CULL_BOTH; break; default: unreachable("not reached"); } } else { dw2 |= GEN6_SF_CULL_NONE; } /* _NEW_SCISSOR _NEW_POLYGON BRW_NEW_GEOMETRY_PROGRAM BRW_NEW_PRIMITIVE */ if (ctx->Scissor.EnableFlags || is_drawing_points(brw) || is_drawing_lines(brw)) dw2 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_LINE */ { uint32_t line_width_u3_7 = brw_get_line_width(brw); dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw2 |= GEN6_SF_LINE_AA_ENABLE; dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } if (ctx->Line.StippleFlag && brw->is_haswell) { dw2 |= HSW_SF_LINE_STIPPLE_ENABLE; } /* _NEW_MULTISAMPLE */ if (multisampled_fbo && ctx->Multisample.Enabled) dw2 |= GEN6_SF_MSRAST_ON_PATTERN; /* FINISHME: Last Pixel Enable? Vertex Sub Pixel Precision Select? */ dw3 = GEN6_SF_LINE_AA_MODE_TRUE; /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw3 |= U_FIXED(CLAMP(point_size, 0.125f, 255.875f), 3); /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(ctx->Polygon.OffsetClamp); /* global depth offset clamp */ ADVANCE_BATCH(); }
static void upload_clip_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t dw1 = brw->meta_in_progress ? 0 : GEN6_CLIP_STATISTICS_ENABLE; uint32_t dw2 = 0; /* _NEW_BUFFERS */ struct gl_framebuffer *fb = ctx->DrawBuffer; /* CACHE_NEW_WM_PROG */ if (brw->wm.prog_data->barycentric_interp_modes & BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) { dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; } if (!ctx->Transform.DepthClamp) dw2 |= GEN6_CLIP_Z_TEST; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { dw2 |= (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } else { dw2 |= (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } /* _NEW_TRANSFORM */ dw2 |= (ctx->Transform.ClipPlanesEnabled << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT); if (ctx->Viewport.X == 0 && ctx->Viewport.Y == 0 && ctx->Viewport.Width == fb->Width && ctx->Viewport.Height == fb->Height) { dw2 |= GEN6_CLIP_GB_TEST; } /* BRW_NEW_RASTERIZER_DISCARD */ if (ctx->RasterDiscard) { dw2 |= GEN6_CLIP_MODE_REJECT_ALL; perf_debug("Rasterizer discard is currently implemented via the clipper; " "having the GS not write primitives would likely be faster."); } BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(dw1); OUT_BATCH(GEN6_CLIP_ENABLE | GEN6_CLIP_API_OGL | GEN6_CLIP_MODE_NORMAL | GEN6_CLIP_XY_TEST | dw2); OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | GEN6_CLIP_FORCE_ZERO_RTAINDEX); ADVANCE_BATCH(); }
/* Recalculate all state from scratch. Perhaps not the most * efficient, but this has gotten complex enough that we need * something which is understandable and reliable. */ static bool i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) { struct gl_context *ctx = &intel->ctx; struct i915_context *i915 = i915_context(ctx); struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = tUnit->_Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); GLuint *state = i915->state.Tex[unit], format, pitch; GLint lodbias, aniso = 0; GLubyte border[4]; GLfloat maxlod; memset(state, 0, sizeof(state)); /*We need to refcount these. */ if (i915->state.tex_buffer[unit] != NULL) { drm_intel_bo_unreference(i915->state.tex_buffer[unit]); i915->state.tex_buffer[unit] = NULL; } if (!intel_finalize_mipmap_tree(intel, unit)) return false; /* Get first image here, since intelObj->firstLevel will get set in * the intel_finalize_mipmap_tree() call above. */ firstImage = tObj->Image[0][tObj->BaseLevel]; drm_intel_bo_reference(intelObj->mt->region->bo); i915->state.tex_buffer[unit] = intelObj->mt->region->bo; i915->state.tex_offset[unit] = intelObj->mt->offset; format = translate_texture_format(firstImage->TexFormat, tObj->DepthMode); pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; state[I915_TEXREG_MS3] = (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format); if (intelObj->mt->region->tiling != I915_TILING_NONE) { state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE; if (intelObj->mt->region->tiling == I915_TILING_Y) state[I915_TEXREG_MS3] |= MS3_TILE_WALK; } /* We get one field with fraction bits for the maximum addressable * (lowest resolution) LOD. Use it to cover both MAX_LEVEL and * MAX_LOD. */ maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK | (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) | ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); { GLuint minFilt, mipFilt, magFilt; switch (sampler->MinFilter) { case GL_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NONE; break; case GL_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_LINEAR; break; default: return false; } if (sampler->MaxAnisotropy > 1.0) { minFilt = FILTER_ANISOTROPIC; magFilt = FILTER_ANISOTROPIC; if (sampler->MaxAnisotropy > 2.0) aniso = SS2_MAX_ANISO_4; else aniso = SS2_MAX_ANISO_2; } else { switch (sampler->MagFilter) { case GL_NEAREST: magFilt = FILTER_NEAREST; break; case GL_LINEAR: magFilt = FILTER_LINEAR; break; default: return false; } } lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0); if (lodbias < -256) lodbias = -256; if (lodbias > 255) lodbias = 255; state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); /* YUV conversion: */ if (firstImage->TexFormat == MESA_FORMAT_YCBCR || firstImage->TexFormat == MESA_FORMAT_YCBCR_REV) state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; /* Shadow: */ if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && tObj->Target != GL_TEXTURE_3D) { if (tObj->Target == GL_TEXTURE_1D) return false; state[I915_TEXREG_SS2] |= (SS2_SHADOW_ENABLE | intel_translate_shadow_compare_func(sampler->CompareFunc)); minFilt = FILTER_4X4_FLAT; magFilt = FILTER_4X4_FLAT; } state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | (mipFilt << SS2_MIP_FILTER_SHIFT) | (magFilt << SS2_MAG_FILTER_SHIFT) | aniso); } { GLenum ws = sampler->WrapS; GLenum wt = sampler->WrapT; GLenum wr = sampler->WrapR; float minlod; /* We program 1D textures as 2D textures, so the 2D texcoord could * result in sampling border values if we don't set the T wrap to * repeat. */ if (tObj->Target == GL_TEXTURE_1D) wt = GL_REPEAT; /* 3D textures don't seem to respect the border color. * Fallback if there's ever a danger that they might refer to * it. * * Effectively this means fallback on 3D clamp or * clamp_to_border. */ if (tObj->Target == GL_TEXTURE_3D && (sampler->MinFilter != GL_NEAREST || sampler->MagFilter != GL_NEAREST) && (ws == GL_CLAMP || wt == GL_CLAMP || wr == GL_CLAMP || ws == GL_CLAMP_TO_BORDER || wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) return false; /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not * used) when using cube map texture coordinates */ if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) || ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE)))) return false; /* * According to 3DSTATE_MAP_STATE at page of 104 in Bspec * Vol3d 3D Instructions: * [DevGDG and DevAlv]: Must be a power of 2 for cube maps. * [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps * must have all faces enabled. * * But, as I tested on pineview(DevBLB derived), the rendering is * bad(you will find the color isn't samplered right in some * fragments). After checking, it seems that the texture layout is * wrong: making the width and height align of 4(although this * doesn't make much sense) will fix this issue and also broke some * others. Well, Bspec mentioned nothing about the layout alignment * and layout for NPOT cube map. I guess the Bspec just assume it's * a POT cube map. * * Thus, I guess we need do this for other platforms as well. */ if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && !is_power_of_two(firstImage->Height)) return false; state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ state[I915_TEXREG_SS3] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) << SS3_MIN_LOD_SHIFT); } /* convert border color from float to ubyte */ CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]); CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]); CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]); CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]); if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { /* GL specs that border color for depth textures is taken from the * R channel, while the hardware uses A. Spam R into all the channels * for safety. */ state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0], border[0], border[0], border[0]); } else { state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3], border[0], border[1], border[2]); } I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true); /* memcmp was already disabled, but definitely won't work as the * region might now change and that wouldn't be detected: */ I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); #if 0 DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); #endif return true; }
static void upload_sf_state(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; /* CACHE_NEW_WM_PROG */ uint32_t num_outputs = brw->wm.prog_data->num_varying_inputs; uint32_t dw1, dw2, dw3, dw4; uint32_t point_sprite_enables; uint32_t flat_enables; int i; /* _NEW_BUFFER */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; const int urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET; float point_size; uint16_t attr_overrides[16]; uint32_t point_sprite_origin; dw1 = GEN6_SF_SWIZZLE_ENABLE | num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT; dw2 = GEN6_SF_STATISTICS_ENABLE | GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; dw3 = 0; dw4 = 0; /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw2 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw2 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw2 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw2 |= GEN6_SF_FRONT_POINT; break; default: assert(0); break; } switch (ctx->Polygon.BackMode) { case GL_FILL: dw2 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw2 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw2 |= GEN6_SF_BACK_POINT; break; default: assert(0); break; } /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) dw3 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_POLYGON */ if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw3 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw3 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw3 |= GEN6_SF_CULL_BOTH; break; default: assert(0); break; } } else { dw3 |= GEN6_SF_CULL_NONE; } /* _NEW_LINE */ { uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); /* TODO: line width of 0 is not allowed when MSAA enabled */ if (line_width_u3_7 == 0) line_width_u3_7 = 1; dw3 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw3 |= GEN6_SF_LINE_AA_ENABLE; dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; dw3 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } /* _NEW_MULTISAMPLE */ if (multisampled_fbo && ctx->Multisample.Enabled) dw3 |= GEN6_SF_MSRAST_ON_PATTERN; /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw4 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); /* * Window coordinates in an FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) { point_sprite_origin = GEN6_SF_POINT_SPRITE_LOWERLEFT; } else { point_sprite_origin = GEN6_SF_POINT_SPRITE_UPPERLEFT; } dw1 |= point_sprite_origin; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw4 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw4 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } /* BRW_NEW_VUE_MAP_GEOM_OUT | _NEW_POINT | _NEW_LIGHT | _NEW_PROGRAM | * CACHE_NEW_WM_PROG */ uint32_t urb_entry_read_length; calculate_attr_overrides(brw, attr_overrides, &point_sprite_enables, &flat_enables, &urb_entry_read_length); dw1 |= (urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT); BEGIN_BATCH(20); OUT_BATCH(_3DSTATE_SF << 16 | (20 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH(dw4); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ for (i = 0; i < 8; i++) { OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16); } OUT_BATCH(point_sprite_enables); /* dw16 */ OUT_BATCH(flat_enables); OUT_BATCH(0); /* wrapshortest enables 0-7 */ OUT_BATCH(0); /* wrapshortest enables 8-15 */ ADVANCE_BATCH(); }
static void upload_clip_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t depth_clamp = 0; uint32_t provoking, userclip; uint32_t dw1 = GEN6_CLIP_STATISTICS_ENABLE; uint32_t nonperspective_barycentric_enable_flag = 0; /* _NEW_BUFFERS */ bool render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0; /* CACHE_NEW_WM_PROG */ if (brw->wm.prog_data->barycentric_interp_modes & (1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC)) { nonperspective_barycentric_enable_flag = GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; } dw1 |= GEN7_CLIP_EARLY_CULL; /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw1 |= GEN7_CLIP_WINDING_CCW; if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw1 |= GEN7_CLIP_CULLMODE_FRONT; break; case GL_BACK: dw1 |= GEN7_CLIP_CULLMODE_BACK; break; case GL_FRONT_AND_BACK: dw1 |= GEN7_CLIP_CULLMODE_BOTH; break; default: assert(!"Should not get here: invalid CullFlag"); break; } } else { dw1 |= GEN7_CLIP_CULLMODE_NONE; } /* _NEW_TRANSFORM */ if (!ctx->Transform.DepthClamp) depth_clamp = GEN6_CLIP_Z_TEST; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { provoking = (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } else { provoking = (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); } /* _NEW_TRANSFORM */ userclip = ctx->Transform.ClipPlanesEnabled; BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(dw1); OUT_BATCH(GEN6_CLIP_ENABLE | GEN6_CLIP_API_OGL | GEN6_CLIP_MODE_NORMAL | nonperspective_barycentric_enable_flag | GEN6_CLIP_XY_TEST | userclip << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT | depth_clamp | provoking); OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | GEN6_CLIP_FORCE_ZERO_RTAINDEX); ADVANCE_BATCH(); }
/* Recalculate all state from scratch. Perhaps not the most * efficient, but this has gotten complex enough that we need * something which is understandable and reliable. */ static bool i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) { struct gl_context *ctx = &intel->ctx; struct i830_context *i830 = i830_context(ctx); struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = tUnit->_Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); GLuint *state = i830->state.Tex[unit], format, pitch; GLint lodbias; GLubyte border[4]; GLuint dst_x, dst_y; memset(state, 0, sizeof(*state)); /*We need to refcount these. */ if (i830->state.tex_buffer[unit] != NULL) { drm_intel_bo_unreference(i830->state.tex_buffer[unit]); i830->state.tex_buffer[unit] = NULL; } if (!intel_finalize_mipmap_tree(intel, unit)) return false; /* Get first image here, since intelObj->firstLevel will get set in * the intel_finalize_mipmap_tree() call above. */ firstImage = tObj->Image[0][tObj->BaseLevel]; intel_miptree_get_image_offset(intelObj->mt, tObj->BaseLevel, 0, &dst_x, &dst_y); drm_intel_bo_reference(intelObj->mt->region->bo); i830->state.tex_buffer[unit] = intelObj->mt->region->bo; pitch = intelObj->mt->region->pitch; /* XXX: This calculation is probably broken for tiled images with * a non-page-aligned offset. */ i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch; format = translate_texture_format(firstImage->TexFormat); state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | (LOAD_TEXTURE_MAP0 << unit) | 4); state[I830_TEXREG_TM0S1] = (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format); if (intelObj->mt->region->tiling != I915_TILING_NONE) { state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE; if (intelObj->mt->region->tiling == I915_TILING_Y) state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK; } state[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK); { if (tObj->Target == GL_TEXTURE_CUBE_MAP) state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) | CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE | CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE | CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE); else state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit)); } { GLuint minFilt, mipFilt, magFilt; float maxlod; uint32_t minlod_fixed, maxlod_fixed; switch (sampler->MinFilter) { case GL_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NONE; break; case GL_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_LINEAR; break; default: return false; } if (sampler->MaxAnisotropy > 1.0) { minFilt = FILTER_ANISOTROPIC; magFilt = FILTER_ANISOTROPIC; } else { switch (sampler->MagFilter) { case GL_NEAREST: magFilt = FILTER_NEAREST; break; case GL_LINEAR: magFilt = FILTER_LINEAR; break; default: return false; } } lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0); if (lodbias < -64) lodbias = -64; if (lodbias > 63) lodbias = 63; state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK); #if 0 /* YUV conversion: */ if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION; #endif /* We get one field with fraction bits for the maximum * addressable (smallest resolution) LOD. Use it to cover both * MAX_LEVEL and MAX_LOD. */ minlod_fixed = U_FIXED(CLAMP(sampler->MinLod, 0.0, 11), 4); maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); if (intel->intelScreen->deviceID == PCI_CHIP_I855_GM || intel->intelScreen->deviceID == PCI_CHIP_I865_G) { maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11.75), 2); maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 3) >> 2); state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT; state[I830_TEXREG_TM0S2] |= TM0S2_LOD_PRECLAMP; } else {
#endif /* We get one field with fraction bits for the maximum * addressable (smallest resolution) LOD. Use it to cover both * MAX_LEVEL and MAX_LOD. */ minlod_fixed = U_FIXED(CLAMP(sampler->MinLod, 0.0, 11), 4); maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); if (intel->intelScreen->deviceID == PCI_CHIP_I855_GM || intel->intelScreen->deviceID == PCI_CHIP_I865_G) { maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11.75), 2); maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 3) >> 2); state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT; state[I830_TEXREG_TM0S2] |= TM0S2_LOD_PRECLAMP; } else { maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11), 0); maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 15) >> 4); state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT_830; } state[I830_TEXREG_TM0S3] |= minlod_fixed << TM0S3_MAX_MIP_SHIFT; state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | (mipFilt << TM0S3_MIP_FILTER_SHIFT) | (magFilt << TM0S3_MAG_FILTER_SHIFT)); } { GLenum ws = sampler->WrapS; GLenum wt = sampler->WrapT; /* 3D textures not available on i830
/** * Sets the sampler state for a single unit. */ static void gen7_update_sampler_state(struct brw_context *brw, int unit, struct gen7_sampler_state *sampler) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj = texUnit->_Current; struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit); bool using_nearest = false; switch (gl_sampler->MinFilter) { case GL_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; using_nearest = true; break; case GL_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; break; default: break; } /* Set Anisotropy: */ if (gl_sampler->MaxAnisotropy > 1.0) { sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC; if (gl_sampler->MaxAnisotropy > 2.0) { sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2, BRW_ANISORATIO_16); } } else { switch (gl_sampler->MagFilter) { case GL_NEAREST: sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; using_nearest = true; break; case GL_LINEAR: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; break; default: break; } } sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR, using_nearest); sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS, using_nearest); sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT, using_nearest); /* Cube-maps on 965 and later must use the same wrap mode for all 3 * coordinate dimensions. Futher, only CUBE and CLAMP are valid. */ if (texObj->Target == GL_TEXTURE_CUBE_MAP) { if (ctx->Texture.CubeMapSeamless && (gl_sampler->MinFilter != GL_NEAREST || gl_sampler->MagFilter != GL_NEAREST)) { sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; } else { sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; } } else if (texObj->Target == GL_TEXTURE_1D) { /* There's a bug in 1D texture sampling - it actually pays * attention to the wrap_t value, though it should not. * Override the wrap_t value here to GL_REPEAT to keep * any nonexistent border pixels from floating in. */ sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP; } /* Set shadow function: */ if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { /* Shadowing is "enabled" by emitting a particular sampler * message (sample_c). So need to recompile WM program when * shadow comparison is enabled on each/any texture unit. */ sampler->ss1.shadow_function = intel_translate_shadow_compare_func(gl_sampler->CompareFunc); } /* Set LOD bias: */ sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias + gl_sampler->LodBias, -16, 15), 8); sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ /* Set BaseMipLevel, MaxLOD, MinLOD: * * XXX: I don't think that using firstLevel, lastLevel works, * because we always setup the surface state as if firstLevel == * level zero. Probably have to subtract firstLevel from each of * these: */ sampler->ss0.base_level = U_FIXED(0, 1); sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8); sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8); upload_default_color(brw, gl_sampler, unit); sampler->ss2.default_color_pointer = brw->wm.sdc_offset[unit] >> 5; }
static void brw_update_sampler_state( const struct pipe_sampler_state *pipe_sampler, unsigned sdc_gs_offset, struct brw_sampler_state *sampler) { memset(sampler, 0, sizeof(*sampler)); switch (pipe_sampler->min_mip_filter) { case PIPE_TEX_FILTER_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; break; case PIPE_TEX_FILTER_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; break; case PIPE_TEX_FILTER_ANISO: sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; break; default: break; } switch (pipe_sampler->min_mip_filter) { case PIPE_TEX_MIPFILTER_NEAREST: sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; break; case PIPE_TEX_MIPFILTER_LINEAR: sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; break; case PIPE_TEX_MIPFILTER_NONE: sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; break; default: break; } /* Set Anisotropy: */ switch (pipe_sampler->mag_img_filter) { case PIPE_TEX_FILTER_NEAREST: sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; break; case PIPE_TEX_FILTER_LINEAR: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; break; case PIPE_TEX_FILTER_ANISO: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; break; default: break; } if (pipe_sampler->max_anisotropy > 2.0) { sampler->ss3.max_aniso = MAX2((pipe_sampler->max_anisotropy - 2) / 2, BRW_ANISORATIO_16); } sampler->ss1.s_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_s); sampler->ss1.r_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_r); sampler->ss1.t_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_t); /* Fulsim complains if I don't do this. Hardware doesn't mind: */ #if 0 if (texObj->Target == GL_TEXTURE_CUBE_MAP_ARB) { sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; } #endif /* Set shadow function: */ if (pipe_sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { /* Shadowing is "enabled" by emitting a particular sampler * message (sample_c). So need to recompile WM program when * shadow comparison is enabled on each/any texture unit. */ sampler->ss0.shadow_function = intel_translate_shadow_compare_func(pipe_sampler->compare_func); } /* Set LOD bias: */ sampler->ss0.lod_bias = S_FIXED(CLAMP(pipe_sampler->lod_bias, -16, 15), 6); sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ /* Set BaseMipLevel, MaxLOD, MinLOD: * * XXX: I don't think that using firstLevel, lastLevel works, * because we always setup the surface state as if firstLevel == * level zero. Probably have to subtract firstLevel from each of * these: */ sampler->ss0.base_level = U_FIXED(0, 1); sampler->ss1.max_lod = U_FIXED(MIN2(MAX2(pipe_sampler->max_lod, 0), 13), 6); sampler->ss1.min_lod = U_FIXED(MIN2(MAX2(pipe_sampler->min_lod, 0), 13), 6); sampler->ss2.default_color_pointer = sdc_gs_offset >> 5; }
/** * Sets the sampler state for a single unit. */ static void gen7_update_sampler_state(struct brw_context *brw, int unit, int ss_index, struct gen7_sampler_state *sampler, uint32_t *sdc_offset) { struct gl_context *ctx = &brw->ctx; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj = texUnit->_Current; struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit); bool using_nearest = false; /* These don't use samplers at all. */ if (texObj->Target == GL_TEXTURE_BUFFER) return; switch (gl_sampler->MinFilter) { case GL_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; using_nearest = true; break; case GL_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; break; default: break; } /* Set Anisotropy: */ if (gl_sampler->MaxAnisotropy > 1.0) { sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC; sampler->ss0.aniso_algorithm = 1; if (gl_sampler->MaxAnisotropy > 2.0) { sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2, BRW_ANISORATIO_16); } } else { switch (gl_sampler->MagFilter) { case GL_NEAREST: sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; using_nearest = true; break; case GL_LINEAR: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; break; default: break; } } sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR, using_nearest); sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS, using_nearest); sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT, using_nearest); /* Cube-maps on 965 and later must use the same wrap mode for all 3 * coordinate dimensions. Futher, only CUBE and CLAMP are valid. */ if (texObj->Target == GL_TEXTURE_CUBE_MAP || texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { if ((ctx->Texture.CubeMapSeamless || gl_sampler->CubeMapSeamless) && (gl_sampler->MinFilter != GL_NEAREST || gl_sampler->MagFilter != GL_NEAREST)) { sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; } else { sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; } } else if (texObj->Target == GL_TEXTURE_1D) { /* There's a bug in 1D texture sampling - it actually pays * attention to the wrap_t value, though it should not. * Override the wrap_t value here to GL_REPEAT to keep * any nonexistent border pixels from floating in. */ sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP; } /* Set shadow function: */ if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { /* Shadowing is "enabled" by emitting a particular sampler * message (sample_c). So need to recompile WM program when * shadow comparison is enabled on each/any texture unit. */ sampler->ss1.shadow_function = intel_translate_shadow_compare_func(gl_sampler->CompareFunc); } /* Set LOD bias: */ sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias + gl_sampler->LodBias, -16, 15), 8); sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ sampler->ss0.base_level = U_FIXED(0, 1); sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8); sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8); /* The sampler can handle non-normalized texture rectangle coordinates * natively */ if (texObj->Target == GL_TEXTURE_RECTANGLE) { sampler->ss3.non_normalized_coord = 1; } upload_default_color(brw, gl_sampler, unit, sdc_offset); sampler->ss2.default_color_pointer = *sdc_offset >> 5; if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST) sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST) sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; }
static void upload_sf_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t dw1, dw2, dw3; float point_size; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(brw->intel.ctx.DrawBuffer); bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; dw1 = GEN6_SF_STATISTICS_ENABLE | GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; /* _NEW_BUFFERS */ dw1 |= (brw_depthbuffer_format(brw) << GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw1 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw1 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_FRONT_POINT; break; default: assert(0); break; } switch (ctx->Polygon.BackMode) { case GL_FILL: dw1 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_BACK_POINT; break; default: assert(0); break; } dw2 = 0; if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw2 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw2 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw2 |= GEN6_SF_CULL_BOTH; break; default: assert(0); break; } } else { dw2 |= GEN6_SF_CULL_NONE; } /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) dw2 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_LINE */ { uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); /* TODO: line width of 0 is not allowed when MSAA enabled */ if (line_width_u3_7 == 0) line_width_u3_7 = 1; dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw2 |= GEN6_SF_LINE_AA_ENABLE; dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } if (ctx->Line.StippleFlag && intel->is_haswell) { dw2 |= HSW_SF_LINE_STIPPLE_ENABLE; } /* _NEW_MULTISAMPLE */ if (multisampled_fbo && ctx->Multisample.Enabled) dw2 |= GEN6_SF_MSRAST_ON_PATTERN; /* FINISHME: Last Pixel Enable? Vertex Sub Pixel Precision Select? */ dw3 = GEN6_SF_LINE_AA_MODE_TRUE; /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw3 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ ADVANCE_BATCH(); }
static void upload_sf_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; /* BRW_NEW_FRAGMENT_PROGRAM */ uint32_t num_outputs = _mesa_bitcount_64(brw->fragment_program->Base.InputsRead); /* _NEW_LIGHT */ bool shade_model_flat = ctx->Light.ShadeModel == GL_FLAT; uint32_t dw1, dw2, dw3, dw4, dw16, dw17; int i; /* _NEW_BUFFER */ bool render_to_fbo = _mesa_is_user_fbo(brw->intel.ctx.DrawBuffer); bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; int attr = 0, input_index = 0; int urb_entry_read_offset = 1; float point_size; uint16_t attr_overrides[FRAG_ATTRIB_MAX]; uint32_t point_sprite_origin; dw1 = GEN6_SF_SWIZZLE_ENABLE | num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT; dw2 = GEN6_SF_STATISTICS_ENABLE | GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; dw3 = 0; dw4 = 0; dw16 = 0; dw17 = 0; /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw2 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw2 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw2 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw2 |= GEN6_SF_FRONT_POINT; break; default: assert(0); break; } switch (ctx->Polygon.BackMode) { case GL_FILL: dw2 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw2 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw2 |= GEN6_SF_BACK_POINT; break; default: assert(0); break; } /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) dw3 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_POLYGON */ if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw3 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw3 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw3 |= GEN6_SF_CULL_BOTH; break; default: assert(0); break; } } else { dw3 |= GEN6_SF_CULL_NONE; } /* _NEW_LINE */ { uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); /* TODO: line width of 0 is not allowed when MSAA enabled */ if (line_width_u3_7 == 0) line_width_u3_7 = 1; dw3 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw3 |= GEN6_SF_LINE_AA_ENABLE; dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; dw3 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } /* _NEW_MULTISAMPLE */ if (multisampled_fbo && ctx->Multisample.Enabled) dw3 |= GEN6_SF_MSRAST_ON_PATTERN; /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw4 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); /* * Window coordinates in an FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) { point_sprite_origin = GEN6_SF_POINT_SPRITE_LOWERLEFT; } else { point_sprite_origin = GEN6_SF_POINT_SPRITE_UPPERLEFT; } dw1 |= point_sprite_origin; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw4 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw4 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } /* Create the mapping from the FS inputs we produce to the VS outputs * they source from. */ uint32_t max_source_attr = 0; for (; attr < FRAG_ATTRIB_MAX; attr++) { enum glsl_interp_qualifier interp_qualifier = brw->fragment_program->InterpQualifier[attr]; bool is_gl_Color = attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1; if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) continue; /* _NEW_POINT */ if (ctx->Point.PointSprite && (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) && ctx->Point.CoordReplace[attr - FRAG_ATTRIB_TEX0]) { dw16 |= (1 << input_index); } if (attr == FRAG_ATTRIB_PNTC) dw16 |= (1 << input_index); /* flat shading */ if (interp_qualifier == INTERP_QUALIFIER_FLAT || (shade_model_flat && is_gl_Color && interp_qualifier == INTERP_QUALIFIER_NONE)) dw17 |= (1 << input_index); /* The hardware can only do the overrides on 16 overrides at a * time, and the other up to 16 have to be lined up so that the * input index = the output index. We'll need to do some * tweaking to make sure that's the case. */ assert(input_index < 16 || attr == input_index); /* CACHE_NEW_VS_PROG | _NEW_LIGHT | _NEW_PROGRAM */ attr_overrides[input_index++] = get_attr_override(&brw->vs.prog_data->vue_map, urb_entry_read_offset, attr, ctx->VertexProgram._TwoSideEnabled, &max_source_attr); } for (; input_index < FRAG_ATTRIB_MAX; input_index++) attr_overrides[input_index] = 0; /* From the Sandy Bridge PRM, Volume 2, Part 1, documentation for * 3DSTATE_SF DWord 1 bits 15:11, "Vertex URB Entry Read Length": * * "This field should be set to the minimum length required to read the * maximum source attribute. The maximum source attribute is indicated * by the maximum value of the enabled Attribute # Source Attribute if * Attribute Swizzle Enable is set, Number of Output Attributes-1 if * enable is not set. * read_length = ceiling((max_source_attr + 1) / 2) * * [errata] Corruption/Hang possible if length programmed larger than * recommended" */ uint32_t urb_entry_read_length = ALIGN(max_source_attr + 1, 2) / 2; dw1 |= urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT; BEGIN_BATCH(20); OUT_BATCH(_3DSTATE_SF << 16 | (20 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH(dw4); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ for (i = 0; i < 8; i++) { OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16); } OUT_BATCH(dw16); /* point sprite texcoord bitmask */ OUT_BATCH(dw17); /* constant interp bitmask */ OUT_BATCH(0); /* wrapshortest enables 0-7 */ OUT_BATCH(0); /* wrapshortest enables 8-15 */ ADVANCE_BATCH(); }
/* Recalculate all state from scratch. Perhaps not the most * efficient, but this has gotten complex enough that we need * something which is understandable and reliable. */ static GLboolean i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) { struct gl_context *ctx = &intel->ctx; struct i915_context *i915 = i915_context(ctx); struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = tUnit->_Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; GLuint *state = i915->state.Tex[unit], format, pitch; GLint lodbias, aniso = 0; GLubyte border[4]; GLfloat maxlod; memset(state, 0, sizeof(state)); /*We need to refcount these. */ if (i915->state.tex_buffer[unit] != NULL) { drm_intel_bo_unreference(i915->state.tex_buffer[unit]); i915->state.tex_buffer[unit] = NULL; } if (!intel_finalize_mipmap_tree(intel, unit)) return GL_FALSE; /* Get first image here, since intelObj->firstLevel will get set in * the intel_finalize_mipmap_tree() call above. */ firstImage = tObj->Image[0][intelObj->firstLevel]; drm_intel_bo_reference(intelObj->mt->region->buffer); i915->state.tex_buffer[unit] = intelObj->mt->region->buffer; i915->state.tex_offset[unit] = 0; /* Always the origin of the miptree */ format = translate_texture_format(firstImage->TexFormat, firstImage->InternalFormat, tObj->DepthMode); pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; state[I915_TEXREG_MS3] = (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format); if (intelObj->mt->region->tiling != I915_TILING_NONE) { state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE; if (intelObj->mt->region->tiling == I915_TILING_Y) state[I915_TEXREG_MS3] |= MS3_TILE_WALK; } /* We get one field with fraction bits for the maximum addressable * (lowest resolution) LOD. Use it to cover both MAX_LEVEL and * MAX_LOD. */ maxlod = MIN2(tObj->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK | (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) | ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); { GLuint minFilt, mipFilt, magFilt; switch (tObj->MinFilter) { case GL_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NONE; break; case GL_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_LINEAR; break; default: return GL_FALSE; } if (tObj->MaxAnisotropy > 1.0) { minFilt = FILTER_ANISOTROPIC; magFilt = FILTER_ANISOTROPIC; if (tObj->MaxAnisotropy > 2.0) aniso = SS2_MAX_ANISO_4; else aniso = SS2_MAX_ANISO_2; } else { switch (tObj->MagFilter) { case GL_NEAREST: magFilt = FILTER_NEAREST; break; case GL_LINEAR: magFilt = FILTER_LINEAR; break; default: return GL_FALSE; } } lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0); if (lodbias < -256) lodbias = -256; if (lodbias > 255) lodbias = 255; state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); /* YUV conversion: */ if (firstImage->TexFormat == MESA_FORMAT_YCBCR || firstImage->TexFormat == MESA_FORMAT_YCBCR_REV) state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; /* Shadow: */ if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && tObj->Target != GL_TEXTURE_3D) { if (tObj->Target == GL_TEXTURE_1D) return GL_FALSE; state[I915_TEXREG_SS2] |= (SS2_SHADOW_ENABLE | intel_translate_shadow_compare_func(tObj->CompareFunc)); minFilt = FILTER_4X4_FLAT; magFilt = FILTER_4X4_FLAT; } state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | (mipFilt << SS2_MIP_FILTER_SHIFT) | (magFilt << SS2_MAG_FILTER_SHIFT) | aniso); } { GLenum ws = tObj->WrapS; GLenum wt = tObj->WrapT; GLenum wr = tObj->WrapR; float minlod; /* We program 1D textures as 2D textures, so the 2D texcoord could * result in sampling border values if we don't set the T wrap to * repeat. */ if (tObj->Target == GL_TEXTURE_1D) wt = GL_REPEAT; /* 3D textures don't seem to respect the border color. * Fallback if there's ever a danger that they might refer to * it. * * Effectively this means fallback on 3D clamp or * clamp_to_border. */ if (tObj->Target == GL_TEXTURE_3D && (tObj->MinFilter != GL_NEAREST || tObj->MagFilter != GL_NEAREST) && (ws == GL_CLAMP || wt == GL_CLAMP || wr == GL_CLAMP || ws == GL_CLAMP_TO_BORDER || wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) return GL_FALSE; /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not * used) when using cube map texture coordinates */ if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) || ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE)))) return GL_FALSE; state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ state[I915_TEXREG_SS3] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); minlod = MIN2(tObj->MinLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) << SS3_MIN_LOD_SHIFT); } /* convert border color from float to ubyte */ CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor.f[0]); CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor.f[1]); CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor.f[2]); CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor.f[3]); if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { /* GL specs that border color for depth textures is taken from the * R channel, while the hardware uses A. Spam R into all the channels * for safety. */ state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0], border[0], border[0], border[0]); } else { state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3], border[0], border[1], border[2]); } I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE); /* memcmp was already disabled, but definitely won't work as the * region might now change and that wouldn't be detected: */ I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); #if 0 DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); #endif return GL_TRUE; }
static void upload_sf_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; GLcontext *ctx = &intel->ctx; /* CACHE_NEW_VS_PROG */ uint32_t num_inputs = brw_count_bits(brw->vs.prog_data->outputs_written); uint32_t num_outputs = brw_count_bits(brw->fragment_program->Base.InputsRead); uint32_t dw1, dw2, dw3, dw4, dw16; int i; /* _NEW_BUFFER */ GLboolean render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0; int attr = 0; dw1 = num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT | (num_inputs + 1) / 2 << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | 1 << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT; dw2 = GEN6_SF_VIEWPORT_TRANSFORM_ENABLE | GEN6_SF_STATISTICS_ENABLE; dw3 = 0; dw4 = 0; dw16 = 0; /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw2 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) dw3 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_POLYGON */ if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw3 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw3 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw3 |= GEN6_SF_CULL_BOTH; break; default: assert(0); break; } } else { dw3 |= GEN6_SF_CULL_NONE; } /* _NEW_LINE */ dw3 |= U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7) << GEN6_SF_LINE_WIDTH_SHIFT; if (ctx->Line.SmoothFlag) { dw3 |= GEN6_SF_LINE_AA_ENABLE; dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; dw3 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } /* _NEW_POINT */ if (ctx->Point._Attenuated) dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 225.875), 3) << GEN6_SF_POINT_WIDTH_SHIFT; if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT; /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw4 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw4 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } if (ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) dw16 |= (1 << i); } } BEGIN_BATCH(20); OUT_BATCH(CMD_3D_SF_STATE << 16 | (20 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH(dw4); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ for (i = 0; i < 8; i++) { uint32_t attr_overrides = 0; for (; attr < 64; attr++) { if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr)) { attr_overrides |= get_attr_override(brw, attr); attr++; break; } } for (; attr < 64; attr++) { if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr)) { attr_overrides |= get_attr_override(brw, attr) << 16; attr++; break; } } OUT_BATCH(attr_overrides); } OUT_BATCH(dw16); /* point sprite texcoord bitmask */ OUT_BATCH(0); /* constant interp bitmask */ OUT_BATCH(0); /* wrapshortest enables 0-7 */ OUT_BATCH(0); /* wrapshortest enables 8-15 */ ADVANCE_BATCH(); intel_batchbuffer_emit_mi_flush(intel->batch); }