📄 s_span.c
字号:
if (!clip_span(ctx, span)) {
return;
}
}
#ifdef DEBUG
/* Make sure all fragments are within window bounds */
if (span->arrayMask & SPAN_XY) {
GLuint i;
for (i = 0; i < span->end; i++) {
if (span->array->mask[i]) {
assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
}
}
}
#endif
/* Polygon Stippling */
if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
stipple_polygon_span(ctx, span);
}
/* Interpolate texcoords? */
if (ctx->Texture._EnabledCoordUnits
&& (span->interpMask & SPAN_TEXTURE)
&& (span->arrayMask & SPAN_TEXTURE) == 0) {
interpolate_texcoords(ctx, span);
}
/* This is the normal place to compute the resulting fragment color/Z.
* As an optimization, we try to defer this until after Z/stencil
* testing in order to try to avoid computing colors that we won't
* actually need.
*/
if (!deferredTexture) {
/* Now we need the rgba array, fill it in if needed */
if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
interpolate_colors(ctx, span);
if (span->interpMask & SPAN_SPEC)
interpolate_specular(ctx, span);
if (span->interpMask & SPAN_FOG)
interpolate_fog(ctx, span);
/* Compute fragment colors with fragment program or texture lookups */
if (ctx->FragmentProgram._Active) {
/* frag prog may need Z values */
if (span->interpMask & SPAN_Z)
_swrast_span_interpolate_z(ctx, span);
_swrast_exec_fragment_program( ctx, span );
}
else if (ctx->ATIFragmentShader._Enabled)
_swrast_exec_fragment_shader( ctx, span );
else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE))
_swrast_texture_span( ctx, span );
/* Do the alpha test */
if (!_swrast_alpha_test(ctx, span)) {
span->arrayMask = origArrayMask;
return;
}
}
/* Stencil and Z testing */
if (ctx->Stencil.Enabled || ctx->Depth.Test) {
if (span->interpMask & SPAN_Z)
_swrast_span_interpolate_z(ctx, span);
if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
/* Combined Z/stencil tests */
if (!_swrast_stencil_and_ztest_span(ctx, span)) {
span->interpMask = origInterpMask;
span->arrayMask = origArrayMask;
return;
}
}
else if (ctx->DrawBuffer->Visual.depthBits > 0) {
/* Just regular depth testing */
ASSERT(ctx->Depth.Test);
ASSERT(span->arrayMask & SPAN_Z);
if (!_swrast_depth_test_span(ctx, span)) {
span->interpMask = origInterpMask;
span->arrayMask = origArrayMask;
return;
}
}
}
/* if we get here, some fragments passed the depth test */
if (ctx->Depth.OcclusionTest) {
ctx->OcclusionResult = GL_TRUE;
}
#if FEATURE_ARB_occlusion_query
if (ctx->Occlusion.Active) {
/* update count of 'passed' fragments */
GLuint i;
for (i = 0; i < span->end; i++)
ctx->Occlusion.PassedCounter += span->array->mask[i];
}
#endif
/* We had to wait until now to check for glColorMask(0,0,0,0) because of
* the occlusion test.
*/
if (colorMask == 0x0) {
span->interpMask = origInterpMask;
span->arrayMask = origArrayMask;
return;
}
/* If we were able to defer fragment color computation to now, there's
* a good chance that many fragments will have already been killed by
* Z/stencil testing.
*/
if (deferredTexture) {
/* Now we need the rgba array, fill it in if needed */
if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
interpolate_colors(ctx, span);
if (span->interpMask & SPAN_SPEC)
interpolate_specular(ctx, span);
if (span->interpMask & SPAN_FOG)
interpolate_fog(ctx, span);
if (ctx->FragmentProgram._Active)
_swrast_exec_fragment_program( ctx, span );
else if (ctx->ATIFragmentShader._Enabled)
_swrast_exec_fragment_shader( ctx, span );
else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE))
_swrast_texture_span( ctx, span );
}
ASSERT(span->arrayMask & SPAN_RGBA);
if (!ctx->FragmentProgram._Enabled) {
/* Add base and specular colors */
if (ctx->Fog.ColorSumEnabled ||
(ctx->Light.Enabled &&
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
if (span->interpMask & SPAN_SPEC) {
interpolate_specular(ctx, span);
}
if (span->arrayMask & SPAN_SPEC) {
add_colors( span->end, span->array->rgba, span->array->spec );
}
else {
/* We probably added the base/specular colors during the
* vertex stage!
*/
}
}
}
/* Fog */
if (swrast->_FogEnabled) {
_swrast_fog_rgba_span(ctx, span);
}
/* Antialias coverage application */
if (span->arrayMask & SPAN_COVERAGE) {
GLchan (*rgba)[4] = span->array->rgba;
GLfloat *coverage = span->array->coverage;
GLuint i;
for (i = 0; i < span->end; i++) {
rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
}
}
if (swrast->_RasterMask & MULTI_DRAW_BIT) {
/* need to do blend/logicop separately for each color buffer */
multi_write_rgba_span(ctx, span);
}
else {
/* normal: write to exactly one buffer */
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
if (ctx->Color._LogicOpEnabled) {
_swrast_logicop_rgba_span(ctx, rb, span, span->array->rgba);
}
else if (ctx->Color.BlendEnabled) {
_swrast_blend_span(ctx, rb, span, span->array->rgba);
}
/* Color component masking */
if (colorMask != 0xffffffff) {
_swrast_mask_rgba_span(ctx, rb, span, span->array->rgba);
}
/* Finally, write the pixels to a color buffer */
if (span->arrayMask & SPAN_XY) {
/* array of pixel coords */
ASSERT(rb->PutValues);
ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
/* XXX check datatype */
rb->PutValues(ctx, rb, span->end, span->array->x, span->array->y,
span->array->rgba, span->array->mask);
}
else {
/* horizontal run of pixels */
ASSERT(rb->PutRow);
ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
/* XXX check datatype */
rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
span->writeAll ? NULL : span->array->mask);
}
}
span->interpMask = origInterpMask;
span->arrayMask = origArrayMask;
}
/**
* Read RGBA pixels from frame buffer. Clipping will be done to prevent
* reading ouside the buffer's boundaries.
*/
void
_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y, GLchan rgba[][4] )
{
const GLint bufWidth = (GLint) rb->Width;
const GLint bufHeight = (GLint) rb->Height;
if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
/* completely above, below, or right */
/* XXX maybe leave rgba values undefined? */
_mesa_bzero(rgba, 4 * n * sizeof(GLchan));
}
else {
GLint skip, length;
if (x < 0) {
/* left edge clipping */
skip = -x;
length = (GLint) n - skip;
if (length < 0) {
/* completely left of window */
return;
}
if (length > bufWidth) {
length = bufWidth;
}
}
else if ((GLint) (x + n) > bufWidth) {
/* right edge clipping */
skip = 0;
length = bufWidth - x;
if (length < 0) {
/* completely to right of window */
return;
}
}
else {
/* no clipping */
skip = 0;
length = (GLint) n;
}
ASSERT(rb);
ASSERT(rb->GetRow);
ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
rb->GetRow(ctx, rb, length, x + skip, y, rgba + skip);
}
}
/**
* Read CI pixels from frame buffer. Clipping will be done to prevent
* reading ouside the buffer's boundaries.
*/
void
_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y, GLuint index[] )
{
const GLint bufWidth = (GLint) rb->Width;
const GLint bufHeight = (GLint) rb->Height;
if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
/* completely above, below, or right */
_mesa_bzero(index, n * sizeof(GLuint));
}
else {
GLint skip, length;
if (x < 0) {
/* left edge clipping */
skip = -x;
length = (GLint) n - skip;
if (length < 0) {
/* completely left of window */
return;
}
if (length > bufWidth) {
length = bufWidth;
}
}
else if ((GLint) (x + n) > bufWidth) {
/* right edge clipping */
skip = 0;
length = bufWidth - x;
if (length < 0) {
/* completely to right of window */
return;
}
}
else {
/* no clipping */
skip = 0;
length = (GLint) n;
}
ASSERT(rb->GetRow);
ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
if (rb->DataType == GL_UNSIGNED_BYTE) {
GLubyte index8[MAX_WIDTH];
GLint i;
rb->GetRow(ctx, rb, length, x + skip, y, index8);
for (i = 0; i < length; i++)
index[skip + i] = index8[i];
}
else if (rb->DataType == GL_UNSIGNED_SHORT) {
GLushort index16[MAX_WIDTH];
GLint i;
rb->GetRow(ctx, rb, length, x + skip, y, index16);
for (i = 0; i < length; i++)
index[skip + i] = index16[i];
}
else if (rb->DataType == GL_UNSIGNED_INT) {
rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
}
}
}
/**
* Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
* reading values outside the buffer bounds.
* We can use this for reading any format/type of renderbuffer.
* \param valueSize is the size in bytes of each value put into the
* values array.
*/
void
_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint count, const GLint x[], const GLint y[],
void *values, GLuint valueSize)
{
GLuint i, inCount = 0, inStart = 0;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 && x[i] < rb->Width && y[i] < rb->Height) {
/* inside */
if (inCount == 0)
inStart = i;
inCount++;
}
else {
if (inCount > 0) {
/* read [inStart, inStart + inCount) */
rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
(GLubyte *) values + inStart * valueSize);
inCount = 0;
}
}
}
if (inCount > 0) {
/* read last values */
rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
(GLubyte *) values + inStart * valueSize);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -