scanline.cpp revision 2ac1cf8a62bcf080b70eaa7c0e4f57d4e8001685
1/** 2 ** 3 ** Copyright 2010, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18#include <assert.h> 19#include <stdio.h> 20#include <string.h> 21 22#include "src/pixelflinger2/pixelflinger2.h" 23#include "src/pixelflinger2/texture.h" 24#include "src/mesa/main/mtypes.h" 25 26#if !USE_LLVM_SCANLINE 27 28static void Saturate(Vec4<BlendComp_t> * color) 29{ 30 color->r = MIN2(MAX2(color->r, 0), 255); 31 color->g = MIN2(MAX2(color->g, 0), 255); 32 color->b = MIN2(MAX2(color->b, 0), 255); 33 color->a = MIN2(MAX2(color->a, 0), 255); 34} 35 36static inline void RGBAIntToRGBAIntx4(unsigned rgba, Vec4<BlendComp_t> * color) __attribute__((always_inline)); 37static inline void RGBAIntToRGBAIntx4(unsigned rgba, Vec4<BlendComp_t> * color) 38{ 39 color->r = rgba & 0xff; 40 color->g = (rgba >>= 8) & 0xff; 41 color->b = (rgba >>= 8) & 0xff; 42 color->a = (rgba >>= 8); 43} 44 45static inline void RGBAFloatx4ToRGBAIntx4(Vector4 * v, Vec4<BlendComp_t> * color) 46{ 47 color->r = v->r * 255; 48 color->g = v->g * 255; 49 color->b = v->b * 255; 50 color->a = v->a * 255; 51} 52 53static inline unsigned RGBAIntx4ToRGBAInt(const Vec4<BlendComp_t> * color); 54static inline unsigned RGBAIntx4ToRGBAInt(const Vec4<BlendComp_t> * color) 55{ 56 return color->r | (color->g << 8) | (color->b << 16) | (color->a << 24); 57} 58 59 60 61//static inline Pixel Vector4ToPixelRGBA(const Vector4 * color) __attribute__((always_inline)); 62//static inline Pixel Vector4ToPixelRGBA(const Vector4 * color) 63//{ 64// Pixel pixel; 65//#if defined(__ARM_HAVE_NEON) && USE_NEON 66// int32x4_t c = vcvtq_s32_f32(vmulq_n_f32(color->f4, 255.0f)); 67// c = vminq_s32(c, vdupq_n_s32(255)); 68// c = vmaxq_s32(c, vdupq_n_s32(0)); 69// pixel.channels[0] = (unsigned char)vgetq_lane_s32(c, 0); 70// pixel.channels[1] = (unsigned char)vgetq_lane_s32(c, 1); 71// pixel.channels[2] = (unsigned char)vgetq_lane_s32(c, 2); 72// pixel.channels[3] = (unsigned char)vgetq_lane_s32(c, 3); 73//#else 74// pixel.channels[0] = (unsigned char)MIN2(MAX2((short)(color->r * 255), 0), 255); 75// pixel.channels[1] = (unsigned char)MIN2(MAX2((short)(color->g * 255), 0), 255); 76// pixel.channels[2] = (unsigned char)MIN2(MAX2((short)(color->b * 255), 0), 255); 77// pixel.channels[3] = (unsigned char)MIN2(MAX2((short)(color->a * 255), 0), 255); 78//#endif //#if USE_FIXED_POINT 79// return pixel; 80//} 81 82template<typename T> 83static inline void BlendFactor(const unsigned mode, T & factor, const T & src, 84 const T & dst, const T & constant, const T & one, 85 const T & zero, const BlendComp_t & srcA, const BlendComp_t & dstA, 86 const BlendComp_t & constantA, const BlendComp_t & sOne) __attribute__((always_inline)); 87template<typename T> 88static inline void BlendFactor(const unsigned mode, T & factor, const T & src, 89 const T & dst, const T & constant, const T & one, 90 const T & zero, const BlendComp_t & srcA, const BlendComp_t & dstA, 91 const BlendComp_t & constantA, const BlendComp_t & sOne) 92{ 93 switch (mode) { 94 case 0: // GL_ZERO 95 factor = zero; 96 return; 97 case 1: // GL_ONE 98 factor = one; 99 return; 100 case 2: // GL_SRC_COLOR: 101 factor = src; 102 return; 103 case 3: // GL_ONE_MINUS_SRC_COLOR: 104 factor = one; 105 factor -= src; 106 return; 107 case 4: // GL_DST_COLOR: 108 factor = dst; 109 return; 110 case 5: // GL_ONE_MINUS_DST_COLOR: 111 factor = one; 112 factor -= dst; 113 return; 114 case 6: // GL_SRC_ALPHA: 115 factor = srcA; 116 return; 117 case 7: // GL_ONE_MINUS_SRC_ALPHA: 118 factor = sOne - srcA; 119 return; 120 case 8: // GL_DST_ALPHA: 121 factor = dstA; 122 return; 123 case 9: // GL_ONE_MINUS_DST_ALPHA: 124 factor = sOne - dstA; 125 return; 126 case 10: // GL_SRC_ALPHA_SATURATE: // valid only for source color; src alpha = 1 127 factor = MIN2(srcA, sOne - dstA); 128 return; 129 case 11: // GL_CONSTANT_COLOR: 130 factor = constant; 131 return; 132 case 12: // GL_ONE_MINUS_CONSTANT_COLOR: 133 factor = one; 134 factor -= constant; 135 return; 136 case 13: // GL_CONSTANT_ALPHA: 137 factor = constantA; 138 return; 139 case 14: // GL_ONE_MINUS_CONSTANT_ALPHA: 140 factor = sOne - constantA; 141 return; 142 default: 143 assert(0); 144 return; 145 } 146} 147 148unsigned char StencilOp(const unsigned op, unsigned char s, const unsigned char ref) 149{ 150 switch (op) { 151 case 0: // GL_ZERO 152 return 0; 153 case 1: // GL_KEEP 154 return s; 155 case 2: // GL_REPLACE 156 return ref; 157 case 3: // GL_INCR 158 if (s < 255) 159 return ++s; 160 return s; 161 case 4: // GL_DECR 162 if (s > 0) 163 return --s; 164 return 0; 165 case 5: // GL_INVERT 166 return ~s; 167 case 6: // GL_INCR_WRAP 168 return ++s; 169 case 7: // GL_DECR_WRAP 170 return --s; 171 default: 172 assert(0); 173 return s; 174 } 175} 176 177#endif // #if !USE_LLVM_SCANLINE 178 179#ifdef USE_LLVM_SCANLINE 180typedef void (* ScanLineFunction_t)(VertexOutput * start, VertexOutput * step, 181 const float (*constants)[4], unsigned * frame, 182 int * depth, unsigned char * stencil, 183 GGLActiveStencil *, unsigned count); 184#endif 185 186void GGLScanLine(const gl_shader_program * program, unsigned * frameBuffer, 187 int * depthBuffer, unsigned char * stencilBuffer, unsigned bufferWidth, 188 unsigned bufferHeight, GGLActiveStencil * activeStencil, const VertexOutput_t * start, 189 const VertexOutput_t * end, const float (*constants)[4]) 190{ 191#if !USE_LLVM_SCANLINE 192 assert(!"only for USE_LLVM_SCANLINE"); 193#endif 194 195 const unsigned int varyingCount = program->VaryingSlots; 196 const unsigned y = start->position.y, startX = start->position.x, 197 endX = end->position.x; 198 199 //assert(ctx->frameSurface.width > startX && ctx->frameSurface.width > endX); 200 //assert(ctx->frameSurface.height > y); 201 202 unsigned * frame = frameBuffer + y * bufferWidth + startX; 203 const VectorComp_t div = VectorComp_t_CTR(1 / (float)(endX - startX)); 204 205 //memcpy(ctx->glCtx->CurrentProgram->ValuesVertexOutput, start, sizeof(*start)); 206 // shader symbols are mapped to gl_shader_program_Values* 207 //VertexOutput & vertex(*(VertexOutput*)ctx->glCtx->CurrentProgram->ValuesVertexOutput); 208 VertexOutput vertex(*start); 209 VertexOutput vertexDx(*end); 210 211 vertexDx.position -= start->position; 212 vertexDx.position *= div; 213 //printf("vertexDx.position.z=%.8g \n", vertexDx.position.z); 214 for (unsigned i = 0; i < varyingCount; i++) { 215 vertexDx.varyings[i] -= start->varyings[i]; 216 vertexDx.varyings[i] *= div; 217 } 218 vertexDx.frontFacingPointCoord -= start->frontFacingPointCoord; 219 vertexDx.frontFacingPointCoord *= div; // gl_PointCoord, only zw 220 vertexDx.frontFacingPointCoord.y = 0; // gl_FrontFacing not interpolated 221 222 int * depth = depthBuffer + y * bufferWidth + startX; 223 unsigned char * stencil = stencilBuffer + y * bufferWidth + startX; 224 225 // TODO DXL consider inverting gl_FragCoord.y 226 ScanLineFunction_t scanLineFunction = (ScanLineFunction_t) 227 program->_LinkedShaders[MESA_SHADER_FRAGMENT]->function; 228 if (endX >= startX) 229 scanLineFunction(&vertex, &vertexDx, constants, frame, depth, stencil, activeStencil, endX - startX + 1); 230 231} 232 233template <bool StencilTest, bool DepthTest, bool DepthWrite, bool BlendEnable> 234void ScanLine(const GGLInterface * iface, const VertexOutput * start, const VertexOutput * end) 235{ 236 GGL_GET_CONST_CONTEXT(ctx, iface); 237 GGLScanLine(ctx->CurrentProgram, (unsigned *)ctx->frameSurface.data, 238 (int *)ctx->depthSurface.data, (unsigned char *)ctx->stencilSurface.data, 239 ctx->frameSurface.width, ctx->frameSurface.height, &ctx->activeStencil, 240 start, end, ctx->CurrentProgram->ValuesUniform); 241// GGL_GET_CONST_CONTEXT(ctx, iface); 242// // assert((unsigned)start->position.y == (unsigned)end->position.y); 243// // 244// // assert(GGL_PIXEL_FORMAT_RGBA_8888 == ctx->frameSurface.format); 245// // assert(GGL_PIXEL_FORMAT_Z_32 == ctx->depthSurface.format); 246// // assert(ctx->frameSurface.width == ctx->depthSurface.width); 247// // assert(ctx->frameSurface.height == ctx->depthSurface.height); 248// 249// const unsigned int varyingCount = ctx->glCtx->CurrentProgram->VaryingSlots; 250// const unsigned y = start->position.y, startX = start->position.x, 251// endX = end->position.x; 252// 253// //assert(ctx->frameSurface.width > startX && ctx->frameSurface.width > endX); 254// //assert(ctx->frameSurface.height > y); 255// 256// unsigned * frame = (unsigned *)ctx->frameSurface.data 257// + y * ctx->frameSurface.width + startX; 258// const VectorComp_t div = VectorComp_t_CTR(1 / (float)(endX - startX)); 259// 260// //memcpy(ctx->glCtx->CurrentProgram->ValuesVertexOutput, start, sizeof(*start)); 261// // shader symbols are mapped to gl_shader_program_Values* 262// //VertexOutput & vertex(*(VertexOutput*)ctx->glCtx->CurrentProgram->ValuesVertexOutput); 263// VertexOutput vertex(*start); 264// VertexOutput vertexDx(*end); 265// 266// vertexDx.position -= start->position; 267// vertexDx.position *= div; 268// //printf("vertexDx.position.z=%.8g \n", vertexDx.position.z); 269// for (unsigned i = 0; i < varyingCount; i++) { 270// vertexDx.varyings[i] -= start->varyings[i]; 271// vertexDx.varyings[i] *= div; 272// } 273// vertexDx.frontFacingPointCoord -= start->frontFacingPointCoord; 274// vertexDx.frontFacingPointCoord *= div; // gl_PointCoord, only zw 275// vertexDx.frontFacingPointCoord.y = 0; // gl_FrontFacing not interpolated 276// 277//#if USE_FORCED_FIXEDPOINT 278// for (unsigned j = 0; j < 4; j++) { 279// for (unsigned i = 0; i < varyingCount; i++) { 280// vertex.varyings[i].i[j] = vertex.varyings[i].f[j] * 65536; 281// vertexDx.varyings[i].i[j] = vertexDx.varyings[i].f[j] * 65536; 282// } 283// vertex.position.i[j] = vertex.position.f[j] * 65536; 284// vertexDx.position.i[j] = vertexDx.position.f[j] * 65536; 285// vertex.frontFacingPointCoord.i[j] = vertex.frontFacingPointCoord.f[j] * 65536; 286// } 287//#endif 288// 289// int * depth = (int *)ctx->depthSurface.data + y * ctx->frameSurface.width + startX; 290// unsigned char * stencil = (unsigned char *)ctx->stencilSurface.data + y * ctx->frameSurface.width + startX; 291// 292//#if !USE_LLVM_TEXTURE_SAMPLER 293// extern const GGLContext * textureGGLContext; 294// textureGGLContext = ctx; 295//#endif 296// 297// // TODO DXL consider inverting gl_FragCoord.y 298// 299//#if USE_LLVM_SCANLINE 300// ScanLineFunction_t scanLineFunction = (ScanLineFunction_t) 301// ctx->glCtx->CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->function; 302// if (endX >= startX) { 303// scanLineFunction(&vertex, &vertexDx, ctx->glCtx->CurrentProgram->ValuesUniform, frame, depth, stencil, &ctx->activeStencil, endX - startX + 1); 304// } 305//#else 306// 307// int z; 308// bool sCmp = true; // default passed, unless failed by stencil test 309// unsigned char s; // masked stored stencil value 310// const unsigned char sMask = ctx->activeStencil.mask; 311// const unsigned char sRef = ctx->activeStencil.ref; 312// const unsigned sFunc = ctx->activeStencil.face ? 0x200 | ctx->backStencil.func : 313// 0x200 | ctx->frontStencil.func; 314// const unsigned ssFail = ctx->activeStencil.face ? ctx->backStencil.sFail : 315// ctx->frontStencil.sFail; 316// const unsigned sdFail = ctx->activeStencil.face ? ctx->backStencil.dFail : 317// ctx->frontStencil.dFail; 318// const unsigned sdPass = ctx->activeStencil.face ? ctx->backStencil.dPass : 319// ctx->frontStencil.dPass; 320// 321// for (unsigned x = startX; x <= endX; x++) { 322// //assert(abs((int)(vertex.position.x) - (int)x) < 2); 323// //assert((unsigned)vertex.position.y == y); 324// if (StencilTest) { 325// s = *stencil & sMask; 326// switch (sFunc) { 327// case GL_NEVER: 328// sCmp = false; 329// break; 330// case GL_LESS: 331// sCmp = sRef < s; 332// break; 333// case GL_EQUAL: 334// sCmp = sRef == s; 335// break; 336// case GL_LEQUAL: 337// sCmp = sRef <= s; 338// break; 339// case GL_GREATER: 340// sCmp = sRef > s; 341// break; 342// case GL_NOTEQUAL: 343// sCmp = sRef != s; 344// break; 345// case GL_GEQUAL: 346// sCmp = sRef >= s; 347// break; 348// case GL_ALWAYS: 349// sCmp = true; 350// break; 351// default: 352// assert(0); 353// break; 354// } 355// } 356// 357// if (!StencilTest || sCmp) { 358// z = vertex.position.i[2]; 359// if (z & 0x80000000) // negative float has leading 1 360// z ^= 0x7fffffff; // bigger negative is smaller 361// bool zCmp = true; 362// if (DepthTest) { 363// switch (0x200 | ctx->state.bufferState.depthFunc) { 364// case GL_NEVER: 365// zCmp = false; 366// break; 367// case GL_LESS: 368// zCmp = z < *depth; 369// break; 370// case GL_EQUAL: 371// zCmp = z == *depth; 372// break; 373// case GL_LEQUAL: 374// zCmp = z <= *depth; 375// break; 376// case GL_GREATER: 377// zCmp = z > *depth; 378// break; 379// case GL_NOTEQUAL: 380// zCmp = z != *depth; 381// break; 382// case GL_GEQUAL: 383// zCmp = z >= *depth; 384// break; 385// case GL_ALWAYS: 386// zCmp = true; 387// break; 388// default: 389// assert(0); 390// break; 391// } 392// } 393// if (!DepthTest || zCmp) { 394// float * varying = (float *)ctx->glCtx->CurrentProgram->ValuesVertexOutput; 395// ShaderFunction_t function = (ShaderFunction_t)ctx->glCtx->CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->function; 396// function(&vertex, &vertex, ctx->glCtx->CurrentProgram->ValuesUniform); 397// //ctx->glCtx->CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->function(); 398// if (BlendEnable) { 399// BlendComp_t sOne = 255, sZero = 0; 400// Vec4<BlendComp_t> one = sOne, zero = sZero; 401// 402// Vec4<BlendComp_t> src; 403//// if (outputRegDesc.IsInt32Color()) 404//// RGBAIntToRGBAIntx4(vertex.fragColor[0].u[0], &src); 405//// else if (outputRegDesc.IsVectorType(Float)) 406// RGBAFloatx4ToRGBAIntx4(&vertex.fragColor[0], &src); 407//// else if (outputRegDesc.IsVectorType(Fixed8)) 408//// { 409//// src.u[0] = vertex.fragColor[0].u[0]; 410//// src.u[1] = vertex.fragColor[0].u[1]; 411//// src.u[2] = vertex.fragColor[0].u[2]; 412//// src.u[3] = vertex.fragColor[0].u[3]; 413//// } 414//// else 415//// assert(0); 416// 417// Vec4<BlendComp_t> dst; 418// unsigned dc = *frame; 419// dst.r = dc & 255; 420// dst.g = (dc >>= 8) & 255; 421// dst.b = (dc >>= 8) & 255; 422// dst.a = (dc >>= 8) & 255; 423// 424// Vec4<BlendComp_t> sf, df; 425// Vec4<BlendComp_t> blendStateColor(ctx->state.blendState.color[0], ctx->state.blendState.color[1], 426// ctx->state.blendState.color[2], ctx->state.blendState.color[3]); 427// 428// BlendFactor(ctx->state.blendState.scf, sf, src, dst, 429// blendStateColor, one, zero, src.a, dst.a, 430// blendStateColor.a, sOne); 431// if (ctx->state.blendState.scf != ctx->state.blendState.saf) 432// BlendFactor(ctx->state.blendState.saf, sf.a, src.a, dst.a, 433// blendStateColor.a, sOne, sZero, src.a, dst.a, 434// blendStateColor.a, sOne); 435// BlendFactor(ctx->state.blendState.dcf, df, src, dst, 436// blendStateColor, one, zero, src.a, dst.a, 437// blendStateColor.a, sOne); 438// if (ctx->state.blendState.dcf != ctx->state.blendState.daf) 439// BlendFactor(ctx->state.blendState.daf, df.a, src.a, dst.a, 440// blendStateColor.a, sOne, sZero, src.a, dst.a, 441// blendStateColor.a, sOne); 442// 443// Vec4<BlendComp_t> sfs(sf), dfs(df); 444// sfs.LShr(7); 445// sf += sfs; 446// dfs.LShr(7); 447// df += dfs; 448// 449// src *= sf; 450// dst *= df; 451// Vec4<BlendComp_t> res(src); 452// switch (ctx->state.blendState.ce + GL_FUNC_ADD) { 453// case GL_FUNC_ADD: 454// res += dst; 455// break; 456// case GL_FUNC_SUBTRACT: 457// res -= dst; 458// break; 459// case GL_FUNC_REVERSE_SUBTRACT: 460// res = dst; 461// res -= src; 462// break; 463// default: 464// assert(0); 465// break; 466// } 467// if (ctx->state.blendState.ce != ctx->state.blendState.ae) 468// switch (ctx->state.blendState.ce + GL_FUNC_ADD) { 469// case GL_FUNC_ADD: 470// res.a = src.a + dst.a; 471// break; 472// case GL_FUNC_SUBTRACT: 473// res.a = src.a - dst.a; 474// break; 475// case GL_FUNC_REVERSE_SUBTRACT: 476// res.a = dst.a - src.a; 477// break; 478// default: 479// assert(0); 480// break; 481// } 482// 483// res.AShr(8); 484// Saturate(&res); 485// *frame = RGBAIntx4ToRGBAInt(&res); 486// } else { 487//// if (outputRegDesc.IsInt32Color()) 488//// *frame = vertex.fragColor[0].u[0]; 489//// else if (outputRegDesc.IsVectorType(Float)) 490// { 491// Vec4<BlendComp_t> src; 492// RGBAFloatx4ToRGBAIntx4(&vertex.fragColor[0], &src); 493// Saturate(&src); 494// *frame = RGBAIntx4ToRGBAInt(&src); 495// } 496//// else if (outputRegDesc.IsVectorType(Fixed16)) 497//// { 498//// Vec4<BlendComp_t> & src = (Vec4<BlendComp_t> &)vertex.fragColor[0]; 499//// src.r = (src.r * 255 >> 16); 500//// src.g = (src.g * 255 >> 16); 501//// src.b = (src.b * 255 >> 16); 502//// src.a = (src.a * 255 >> 16); 503//// Saturate(&src); 504//// *frame = RGBAIntx4ToRGBAInt(&src); 505//// } 506//// else if (outputRegDesc.IsVectorType(Fixed8)) 507//// { 508//// Vec4<BlendComp_t> & src = (Vec4<BlendComp_t> &)vertex.fragColor[0]; 509//// Saturate(&src); 510//// *frame = RGBAIntx4ToRGBAInt(&src); 511//// } 512//// else 513//// assert(0); 514// } 515// 516// if (DepthWrite) 517// *depth = z; 518// if (StencilTest) 519// *stencil = StencilOp(sdPass, s, sRef); 520// } else if (StencilTest) 521// *stencil = StencilOp(sdFail, s, sRef); 522// } else if (StencilTest) 523// *stencil = StencilOp(ssFail, s, sRef); 524// 525// frame++; 526// depth++; 527// stencil++; 528// 529//#if USE_FORCED_FIXEDPOINT 530// for (unsigned j = 0; j < 4; j++) { 531// if (ctx->glCtx->Shader.CurrentProgram->FragmentProgram->UsesFragCoord) 532// vertex.position.i[j] += vertexDx.position.i[j]; 533// for (unsigned i = 0; i < varyingCount; i++) 534// vertex.varyings[i].i[j] += vertexDx.varyings[i].i[j]; 535// } 536// vertex.position.i[2] += vertexDx.position.i[2]; 537// if (ctx->glCtx->Shader.CurrentProgram->FragmentProgram->UsesPointCoord) { 538// vertex.frontFacingPointCoord.i[2] = vertexDx.frontFacingPointCoord.i[2]; 539// vertex.frontFacingPointCoord.i[3] = vertexDx.frontFacingPointCoord.i[3]; 540// } 541//#else 542// if (ctx->glCtx->CurrentProgram->UsesFragCoord) 543// vertex.position += vertexDx.position; 544// else if (ctx->state.bufferState.depthTest) 545// vertex.position.z += vertexDx.position.z; 546// 547// for (unsigned i = 0; i < varyingCount; i++) 548// vertex.varyings[i] += vertexDx.varyings[i]; 549// if (ctx->glCtx->CurrentProgram->UsesPointCoord) { 550// vertex.frontFacingPointCoord.z += vertexDx.frontFacingPointCoord.z; 551// vertex.frontFacingPointCoord.w += vertexDx.frontFacingPointCoord.w; 552// } 553//#endif // #if USE_FORCED_FIXEDPOINT 554// } 555// 556//#endif // #if USE_LLVM_SCANLINE 557// 558//#if !USE_LLVM_TEXTURE_SAMPLER 559// textureGGLContext = NULL; 560//#endif 561} 562 563static void PickScanLine(GGLInterface * iface) 564{ 565 GGL_GET_CONTEXT(ctx, iface); 566 567 ctx->interface.ScanLine = NULL; 568 if (ctx->state.bufferState.stencilTest) { 569 if (ctx->state.bufferState.depthTest) { 570 if (ctx->state.blendState.enable) 571 ctx->interface.ScanLine = ScanLine<true, true, true, true>; 572 else 573 ctx->interface.ScanLine = ScanLine<true, true, true, false>; 574 } else { 575 if (ctx->state.blendState.enable) 576 ctx->interface.ScanLine = ScanLine<true, false, false, true>; 577 else 578 ctx->interface.ScanLine = ScanLine<true, false, false, false>; 579 } 580 } else { 581 if (ctx->state.bufferState.depthTest) { 582 if (ctx->state.blendState.enable) 583 ctx->interface.ScanLine = ScanLine<false, true, true, true>; 584 else 585 ctx->interface.ScanLine = ScanLine<false, true, true, false>; 586 } else { 587 if (ctx->state.blendState.enable) 588 ctx->interface.ScanLine = ScanLine<false, false, false, true>; 589 else 590 ctx->interface.ScanLine = ScanLine<false, false, false, false>; 591 } 592 } 593 594 assert(ctx->interface.ScanLine); 595} 596 597void InitializeScanLineFunctions(GGLInterface * iface) 598{ 599 GGL_GET_CONTEXT(ctx, iface); 600 ctx->PickScanLine = PickScanLine; 601} 602