void nv04_emit_blend(struct gl_context *ctx, int emit) { struct nv04_context *nv04 = to_nv04_context(ctx); nv04->blend &= NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK; nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT_MSB | NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE; /* Alpha blending. */ nv04->blend |= get_blend_func(ctx->Color.Blend[0].DstRGB) << 28 | get_blend_func(ctx->Color.Blend[0].SrcRGB) << 24; if (ctx->Color.BlendEnabled) nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE; /* Shade model. */ if (ctx->Light.ShadeModel == GL_SMOOTH) nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD; else nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT; /* Secondary color */ if (_mesa_need_secondary_color(ctx)) nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE; /* Fog. */ if (ctx->Fog.Enabled) { nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE; nv04->fog = pack_rgba_f(MESA_FORMAT_B8G8R8A8_UNORM, ctx->Fog.Color); } }
static void update_separate_specular(struct gl_context *ctx) { if (_mesa_need_secondary_color(ctx)) ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; else ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR; }
static void update_specular(struct gl_context * ctx) { struct i830_context *i830 = i830_context(ctx); I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; if (_mesa_need_secondary_color(ctx)) i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_SPEC_ADD; else i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD; }
static void update_tricaps(struct gl_context *ctx, GLbitfield new_state) { ctx->_TriangleCaps = 0; /* * Points */ if (1/*new_state & _NEW_POINT*/) { if (ctx->Point.SmoothFlag) ctx->_TriangleCaps |= DD_POINT_SMOOTH; if (ctx->Point._Attenuated) ctx->_TriangleCaps |= DD_POINT_ATTEN; } /* * Lines */ if (1/*new_state & _NEW_LINE*/) { if (ctx->Line.SmoothFlag) ctx->_TriangleCaps |= DD_LINE_SMOOTH; if (ctx->Line.StippleFlag) ctx->_TriangleCaps |= DD_LINE_STIPPLE; } /* * Polygons */ if (1/*new_state & _NEW_POLYGON*/) { if (ctx->Polygon.SmoothFlag) ctx->_TriangleCaps |= DD_TRI_SMOOTH; if (ctx->Polygon.StippleFlag) ctx->_TriangleCaps |= DD_TRI_STIPPLE; if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) ctx->_TriangleCaps |= DD_TRI_UNFILLED; if (ctx->Polygon.OffsetPoint || ctx->Polygon.OffsetLine || ctx->Polygon.OffsetFill) ctx->_TriangleCaps |= DD_TRI_OFFSET; } /* * Lighting and shading */ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; if (_mesa_need_secondary_color(ctx)) ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; }
/* * Examine GL state and set swrast->Triangle to an * appropriate antialiased triangle rasterizer function. */ void _swrast_set_aa_triangle_function(struct gl_context *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); ASSERT(ctx->Polygon.SmoothFlag); if (ctx->Texture._EnabledCoord || swrast->_FogEnabled || _mesa_need_secondary_color(ctx)) { SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri; } else { SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri; } ASSERT(SWRAST_CONTEXT(ctx)->Triangle); }
/* TCL render. */ static GLboolean r200_run_tcl_render( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLuint i; GLubyte *vimap_rev; /* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use more than 12 of those at the same time. */ GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; /* TODO: separate this from the swtnl pipeline */ if (rmesa->radeon.TclFallback) return GL_TRUE; /* fallback to software t&l */ radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __func__); if (VB->Count == 0) return GL_FALSE; /* Validate state: */ if (rmesa->radeon.NewGLState) if (!r200ValidateState( ctx )) return GL_TRUE; /* fallback to sw t&l */ if (!_mesa_arb_vertex_program_enabled(ctx)) { /* NOTE: inputs != tnl->render_inputs - these are the untransformed * inputs. */ map_rev_fixed[0] = VERT_ATTRIB_POS; /* technically there is no reason we always need VA_COLOR0. In theory could disable it depending on lighting, color materials, texturing... */ map_rev_fixed[4] = VERT_ATTRIB_COLOR0; if (ctx->Light.Enabled) { map_rev_fixed[2] = VERT_ATTRIB_NORMAL; } /* this also enables VA_COLOR1 when using separate specular lighting model, which is unnecessary. FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses the secondary color (if lighting is disabled). The chip seems misconfigured for that though elsewhere (tcl output, might lock up) */ if (_mesa_need_secondary_color(ctx)) { map_rev_fixed[5] = VERT_ATTRIB_COLOR1; } if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) { map_rev_fixed[3] = VERT_ATTRIB_FOG; } for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) { if (ctx->Texture.Unit[i]._Current) { if (rmesa->TexGenNeedNormals[i]) { map_rev_fixed[2] = VERT_ATTRIB_NORMAL; } map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i; } } vimap_rev = &map_rev_fixed[0]; } else { /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment part", since using some vertex interpolator later which is not in out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex prog to a not enabled output however, so just don't mess with it. We only need to change compsel. */ GLuint out_compsel = 0; const GLbitfield64 vp_out = rmesa->curr_vp_hw->mesa_program.info.outputs_written; vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0]; assert(vp_out & BITFIELD64_BIT(VARYING_SLOT_POS)); out_compsel = R200_OUTPUT_XYZW; if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL0)) { out_compsel |= R200_OUTPUT_COLOR_0; } if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL1)) { out_compsel |= R200_OUTPUT_COLOR_1; } if (vp_out & BITFIELD64_BIT(VARYING_SLOT_FOGC)) { out_compsel |= R200_OUTPUT_DISCRETE_FOG; } if (vp_out & BITFIELD64_BIT(VARYING_SLOT_PSIZ)) { out_compsel |= R200_OUTPUT_PT_SIZE; } for (i = VARYING_SLOT_TEX0; i < VARYING_SLOT_TEX6; i++) { if (vp_out & BITFIELD64_BIT(i)) { out_compsel |= R200_OUTPUT_TEX_0 << (i - VARYING_SLOT_TEX0); } } if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) { R200_STATECHANGE( rmesa, vtx ); rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel; } } /* Do the actual work: */ radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ ); GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev ) + rmesa->radeon.cmdbuf.cs->cdw; r200EmitArrays( ctx, vimap_rev ); for (i = 0 ; i < VB->PrimitiveCount ; i++) { GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); GLuint start = VB->Primitive[i].start; GLuint length = VB->Primitive[i].count; if (!length) continue; if (VB->Elts) r200EmitEltPrimitive( ctx, start, start+length, prim ); else r200EmitPrimitive( ctx, start, start+length, prim ); } if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw ) WARN_ONCE("Rendering was %d commands larger than predicted size." " We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end); return GL_FALSE; /* finished the pipe */ }
/* * Render a bitmap. */ static bool do_blit_bitmap( struct gl_context *ctx, GLint dstx, GLint dsty, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct intel_context *intel = intel_context(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct intel_renderbuffer *irb; GLfloat tmpColor[4]; GLubyte ubcolor[4]; GLuint color; GLsizei bitmap_width = width; GLsizei bitmap_height = height; GLint px, py; GLuint stipple[32]; GLint orig_dstx = dstx; GLint orig_dsty = dsty; /* Update draw buffer bounds */ _mesa_update_state(ctx); if (ctx->Depth.Test) { /* The blit path produces incorrect results when depth testing is on. * It seems the blit Z coord is always 1.0 (the far plane) so fragments * will likely be obscured by other, closer geometry. */ return false; } intel_prepare_render(intel); if (fb->_NumColorDrawBuffers != 1) { perf_debug("accelerated glBitmap() only supports rendering to a " "single color buffer\n"); return false; } irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); if (_mesa_is_bufferobj(unpack->BufferObj)) { bitmap = map_pbo(ctx, width, height, unpack, bitmap); if (bitmap == NULL) return true; /* even though this is an error, we're done */ } COPY_4V(tmpColor, ctx->Current.RasterColor); if (_mesa_need_secondary_color(ctx)) { ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor); } UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]); UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]); switch (irb->mt->format) { case MESA_FORMAT_B8G8R8A8_UNORM: case MESA_FORMAT_B8G8R8X8_UNORM: color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]); break; case MESA_FORMAT_B5G6R5_UNORM: color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]); break; default: perf_debug("Unsupported format %s in accelerated glBitmap()\n", _mesa_get_format_name(irb->mt->format)); return false; } if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) return false; /* Clip to buffer bounds and scissor. */ if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, &dstx, &dsty, &width, &height)) goto out; dsty = y_flip(fb, dsty, height); #define DY 32 #define DX 32 /* Chop it all into chunks that can be digested by hardware: */ for (py = 0; py < height; py += DY) { for (px = 0; px < width; px += DX) { int h = MIN2(DY, height - py); int w = MIN2(DX, width - px); GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8; GLenum logic_op = ctx->Color.ColorLogicOpEnabled ? ctx->Color.LogicOp : GL_COPY; assert(sz <= sizeof(stipple)); memset(stipple, 0, sz); /* May need to adjust this when padding has been introduced in * sz above: * * Have to translate destination coordinates back into source * coordinates. */ int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack, bitmap, -orig_dstx + (dstx + px), -orig_dsty + y_flip(fb, dsty + py, h), w, h, (GLubyte *)stipple, 8, _mesa_is_winsys_fbo(fb)); if (count == 0) continue; if (!intelEmitImmediateColorExpandBlit(intel, irb->mt->cpp, (GLubyte *)stipple, sz, color, irb->mt->region->pitch, irb->mt->region->bo, 0, irb->mt->region->tiling, dstx + px, dsty + py, w, h, logic_op)) { return false; } if (ctx->Query.CurrentOcclusionObject) ctx->Query.CurrentOcclusionObject->Result += count; } } out: if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) intel_batchbuffer_flush(intel); if (_mesa_is_bufferobj(unpack->BufferObj)) { /* done with PBO so unmap it now */ ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } intel_check_front_buffer_rendering(intel); return true; }
/* TCL render. */ static GLboolean radeon_run_tcl_render( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) { r100ContextPtr rmesa = R100_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0; GLuint i; GLuint emit_end; /* TODO: separate this from the swtnl pipeline */ if (rmesa->radeon.TclFallback) return GL_TRUE; /* fallback to software t&l */ if (VB->Count == 0) return GL_FALSE; /* NOTE: inputs != tnl->render_inputs - these are the untransformed * inputs. */ if (ctx->Light.Enabled) { inputs |= VERT_BIT_NORMAL; } if (_mesa_need_secondary_color(ctx)) { inputs |= VERT_BIT_COLOR1; } if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) { inputs |= VERT_BIT_FOG; } for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) { if (ctx->Texture.Unit[i]._Current) { /* TODO: probably should not emit texture coords when texgen is enabled */ if (rmesa->TexGenNeedNormals[i]) { inputs |= VERT_BIT_NORMAL; } inputs |= VERT_BIT_TEX(i); } } radeonReleaseArrays( ctx, ~0 ); emit_end = radeonEnsureEmitSize( ctx, inputs ) + rmesa->radeon.cmdbuf.cs->cdw; radeonEmitArrays( ctx, inputs ); rmesa->tcl.Elts = VB->Elts; for (i = 0 ; i < VB->PrimitiveCount ; i++) { GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); GLuint start = VB->Primitive[i].start; GLuint length = VB->Primitive[i].count; if (!length) continue; if (rmesa->tcl.Elts) radeonEmitEltPrimitive( ctx, start, start+length, prim ); else radeonEmitPrimitive( ctx, start, start+length, prim ); } if (emit_end < rmesa->radeon.cmdbuf.cs->cdw) WARN_ONCE("Rendering was %d commands larger than predicted size." " We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end); return GL_FALSE; /* finished the pipe */ }
void _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state ) { TNLcontext *tnl = TNL_CONTEXT(ctx); const struct gl_vertex_program *vp = ctx->VertexProgram._Current; const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; GLuint i; if (new_state & (_NEW_HINT | _NEW_PROGRAM)) { ASSERT(tnl->AllowVertexFog || tnl->AllowPixelFog); tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST)) || !tnl->AllowPixelFog) && !fp; } tnl->pipeline.new_state |= new_state; /* Calculate tnl->render_inputs. This bitmask indicates which vertex * attributes need to be emitted to the rasterizer. */ RENDERINPUTS_ZERO( tnl->render_inputs_bitset ); RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS ); if (!fp || (fp->Base.InputsRead & FRAG_BIT_COL0)) { RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR0 ); } if (_mesa_need_secondary_color(ctx)) RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 ); for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { if (ctx->Texture._EnabledCoordUnits & (1 << i) || (fp && fp->Base.InputsRead & FRAG_BIT_TEX(i))) { RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX(i) ); } } if (ctx->Fog.Enabled || (fp != NULL && (fp->Base.InputsRead & FRAG_BIT_FOGC) != 0)) { /* Either fixed-function fog or a fragment program needs fog coord. */ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG ); } if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_EDGEFLAG ); if (ctx->RenderMode == GL_FEEDBACK) RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 ); if (ctx->Point._Attenuated || (ctx->VertexProgram._Enabled && ctx->VertexProgram.PointSizeEnabled)) RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POINTSIZE ); /* check for varying vars which are written by the vertex program */ if (vp) { GLuint i; for (i = 0; i < MAX_VARYING; i++) { if (vp->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) { RENDERINPUTS_SET(tnl->render_inputs_bitset, _TNL_ATTRIB_GENERIC(i)); } } } }