scanline.cpp revision 3225321119408735f16b72b539c9fb7d80683552
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#endif // #if !USE_LLVM_SCANLINE 148 149unsigned char StencilOp(const unsigned op, unsigned char s, const unsigned char ref) 150{ 151 switch (op) { 152 case 0: // GL_ZERO 153 return 0; 154 case 1: // GL_KEEP 155 return s; 156 case 2: // GL_REPLACE 157 return ref; 158 case 3: // GL_INCR 159 if (s < 255) 160 return ++s; 161 return s; 162 case 4: // GL_DECR 163 if (s > 0) 164 return --s; 165 return 0; 166 case 5: // GL_INVERT 167 return ~s; 168 case 6: // GL_INCR_WRAP 169 return ++s; 170 case 7: // GL_DECR_WRAP 171 return --s; 172 default: 173 assert(0); 174 return s; 175 } 176} 177 178template <bool StencilTest, bool DepthTest, bool DepthWrite, bool BlendEnable> 179void ScanLine(const GGLInterface * iface, const VertexOutput * v1, const VertexOutput * v2) 180{ 181 GGL_GET_CONST_CONTEXT(ctx, iface); 182 // assert((unsigned)v1->position.y == (unsigned)v2->position.y); 183 // 184 // assert(GGL_PIXEL_FORMAT_RGBA_8888 == ctx->frameSurface.format); 185 // assert(GGL_PIXEL_FORMAT_Z_32 == ctx->depthSurface.format); 186 // assert(ctx->frameSurface.width == ctx->depthSurface.width); 187 // assert(ctx->frameSurface.height == ctx->depthSurface.height); 188 189 const unsigned int varyingCount = ctx->glCtx->CurrentProgram->VaryingSlots; 190 const unsigned y = v1->position.y, startX = v1->position.x, 191 endX = v2->position.x; 192 193 //assert(ctx->frameSurface.width > startX && ctx->frameSurface.width > endX); 194 //assert(ctx->frameSurface.height > y); 195 196 unsigned * frame = (unsigned *)ctx->frameSurface.data 197 + y * ctx->frameSurface.width + startX; 198 const VectorComp_t div = VectorComp_t_CTR(1 / (float)(endX - startX)); 199 200 memcpy(ctx->glCtx->CurrentProgram->ValuesVertexOutput, v1, sizeof(*v1)); 201 // shader symbols are mapped to gl_shader_program_Values* 202 VertexOutput & vertex(*(VertexOutput*)ctx->glCtx->CurrentProgram->ValuesVertexOutput); 203 VertexOutput vertexDx(*v2); 204 205 vertexDx.position -= v1->position; 206 vertexDx.position *= div; 207 //printf("vertexDx.position.z=%.8g \n", vertexDx.position.z); 208 for (unsigned i = 0; i < varyingCount; i++) { 209 vertexDx.varyings[i] -= v1->varyings[i]; 210 vertexDx.varyings[i] *= div; 211 } 212 vertexDx.frontFacingPointCoord -= v1->frontFacingPointCoord; 213 vertexDx.frontFacingPointCoord *= div; // gl_PointCoord, only zw 214 vertexDx.frontFacingPointCoord.y = 0; // gl_FrontFacing not interpolated 215 216#if USE_FORCED_FIXEDPOINT 217 for (unsigned j = 0; j < 4; j++) { 218 for (unsigned i = 0; i < varyingCount; i++) { 219 vertex.varyings[i].i[j] = vertex.varyings[i].f[j] * 65536; 220 vertexDx.varyings[i].i[j] = vertexDx.varyings[i].f[j] * 65536; 221 } 222 vertex.position.i[j] = vertex.position.f[j] * 65536; 223 vertexDx.position.i[j] = vertexDx.position.f[j] * 65536; 224 vertex.frontFacingPointCoord.i[j] = vertex.frontFacingPointCoord.f[j] * 65536; 225 } 226#endif 227 228 int * depth = (int *)ctx->depthSurface.data + y * ctx->frameSurface.width + startX; 229 unsigned char * stencil = (unsigned char *)ctx->stencilSurface.data + y * ctx->frameSurface.width + startX; 230 231#if !USE_LLVM_TEXTURE_SAMPLER 232 extern const GGLContext * textureGGLContext; 233 textureGGLContext = ctx; 234#endif 235 236 // TODO DXL consider inverting gl_FragCoord.y 237 238#if USE_LLVM_SCANLINE 239 typedef void (* ScanLineFunction_t)(VertexOutput * start, VertexOutput * step, 240 unsigned * frame, int * depth, unsigned char * stencil, 241 GGLContext::ActiveStencilState *, unsigned count); 242 243 ScanLineFunction_t scanLineFunction = (ScanLineFunction_t) 244 ctx->glCtx->CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->function; 245 if (endX >= startX) { 246 scanLineFunction(&vertex, &vertexDx, frame, depth, stencil, &ctx->activeStencil, endX - startX + 1); 247 } 248#else 249 250 int z; 251 bool sCmp = true; // default passed, unless failed by stencil test 252 unsigned char s; // masked stored stencil value 253 const unsigned char sMask = ctx->activeStencil.mask; 254 const unsigned char sRef = ctx->activeStencil.ref; 255 const unsigned sFunc = ctx->activeStencil.face ? 0x200 | ctx->backStencil.func : 256 0x200 | ctx->frontStencil.func; 257 const unsigned ssFail = ctx->activeStencil.face ? ctx->backStencil.sFail : 258 ctx->frontStencil.sFail; 259 const unsigned sdFail = ctx->activeStencil.face ? ctx->backStencil.dFail : 260 ctx->frontStencil.dFail; 261 const unsigned sdPass = ctx->activeStencil.face ? ctx->backStencil.dPass : 262 ctx->frontStencil.dPass; 263 264 for (unsigned x = startX; x <= endX; x++) { 265 //assert(abs((int)(vertex.position.x) - (int)x) < 2); 266 //assert((unsigned)vertex.position.y == y); 267 if (StencilTest) { 268 s = *stencil & sMask; 269 switch (sFunc) { 270 case GL_NEVER: 271 sCmp = false; 272 break; 273 case GL_LESS: 274 sCmp = sRef < s; 275 break; 276 case GL_EQUAL: 277 sCmp = sRef == s; 278 break; 279 case GL_LEQUAL: 280 sCmp = sRef <= s; 281 break; 282 case GL_GREATER: 283 sCmp = sRef > s; 284 break; 285 case GL_NOTEQUAL: 286 sCmp = sRef != s; 287 break; 288 case GL_GEQUAL: 289 sCmp = sRef >= s; 290 break; 291 case GL_ALWAYS: 292 sCmp = true; 293 break; 294 default: 295 assert(0); 296 break; 297 } 298 } 299 300 if (!StencilTest || sCmp) { 301 z = vertex.position.i[2]; 302 if (z & 0x80000000) // negative float has leading 1 303 z ^= 0x7fffffff; // bigger negative is smaller 304 bool zCmp = true; 305 if (DepthTest) 306 { 307 switch (0x200 | ctx->bufferState.depthFunc) { 308 case GL_NEVER: 309 zCmp = false; 310 break; 311 case GL_LESS: 312 zCmp = z < *depth; 313 break; 314 case GL_EQUAL: 315 zCmp = z == *depth; 316 break; 317 case GL_LEQUAL: 318 zCmp = z <= *depth; 319 break; 320 case GL_GREATER: 321 zCmp = z > *depth; 322 break; 323 case GL_NOTEQUAL: 324 zCmp = z != *depth; 325 break; 326 case GL_GEQUAL: 327 zCmp = z >= *depth; 328 break; 329 case GL_ALWAYS: 330 zCmp = true; 331 break; 332 default: 333 assert(0); 334 break; 335 } 336 } 337 if (!DepthTest || zCmp) { 338 float * varying = (float *)ctx->glCtx->CurrentProgram->ValuesVertexOutput; 339 340 assert((void *)&(vertex.varyings[0]) == &(varying[2 * 4])); 341 ctx->glCtx->CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->function(); 342 if (BlendEnable) { 343 BlendComp_t sOne = 255, sZero = 0; 344 Vec4<BlendComp_t> one = sOne, zero = sZero; 345 346 Vec4<BlendComp_t> src; 347// if (outputRegDesc.IsInt32Color()) 348// RGBAIntToRGBAIntx4(vertex.fragColor[0].u[0], &src); 349// else if (outputRegDesc.IsVectorType(Float)) 350 RGBAFloatx4ToRGBAIntx4(&vertex.fragColor[0], &src); 351// else if (outputRegDesc.IsVectorType(Fixed8)) 352// { 353// src.u[0] = vertex.fragColor[0].u[0]; 354// src.u[1] = vertex.fragColor[0].u[1]; 355// src.u[2] = vertex.fragColor[0].u[2]; 356// src.u[3] = vertex.fragColor[0].u[3]; 357// } 358// else 359// assert(0); 360 361 Vec4<BlendComp_t> dst; 362 unsigned dc = *frame; 363 dst.r = dc & 255; 364 dst.g = (dc >>= 8) & 255; 365 dst.b = (dc >>= 8) & 255; 366 dst.a = (dc >>= 8) & 255; 367 368 Vec4<BlendComp_t> sf, df; 369 370 BlendFactor(ctx->blendState.scf, sf, src, dst, 371 ctx->blendState.color, one, zero, src.a, dst.a, 372 ctx->blendState.color.a, sOne); 373 if (ctx->blendState.scf != ctx->blendState.saf) 374 BlendFactor(ctx->blendState.saf, sf.a, src.a, dst.a, 375 ctx->blendState.color.a, sOne, sZero, src.a, dst.a, 376 ctx->blendState.color.a, sOne); 377 BlendFactor(ctx->blendState.dcf, df, src, dst, 378 ctx->blendState.color, one, zero, src.a, dst.a, 379 ctx->blendState.color.a, sOne); 380 if (ctx->blendState.dcf != ctx->blendState.daf) 381 BlendFactor(ctx->blendState.daf, df.a, src.a, dst.a, 382 ctx->blendState.color.a, sOne, sZero, src.a, dst.a, 383 ctx->blendState.color.a, sOne); 384 385 Vec4<BlendComp_t> sfs(sf), dfs(df); 386 sfs.LShr(7); 387 sf += sfs; 388 dfs.LShr(7); 389 df += dfs; 390 391 src *= sf; 392 dst *= df; 393 Vec4<BlendComp_t> res(src); 394 switch (ctx->blendState.ce + GL_FUNC_ADD) { 395 case GL_FUNC_ADD: 396 res += dst; 397 break; 398 case GL_FUNC_SUBTRACT: 399 res -= dst; 400 break; 401 case GL_FUNC_REVERSE_SUBTRACT: 402 res = dst; 403 res -= src; 404 break; 405 default: 406 assert(0); 407 break; 408 } 409 if (ctx->blendState.ce != ctx->blendState.ae) 410 switch (ctx->blendState.ce + GL_FUNC_ADD) { 411 case GL_FUNC_ADD: 412 res.a = src.a + dst.a; 413 break; 414 case GL_FUNC_SUBTRACT: 415 res.a = src.a - dst.a; 416 break; 417 case GL_FUNC_REVERSE_SUBTRACT: 418 res.a = dst.a - src.a; 419 break; 420 default: 421 assert(0); 422 break; 423 } 424 425 res.AShr(8); 426 Saturate(&res); 427 *frame = RGBAIntx4ToRGBAInt(&res); 428 } else { 429// if (outputRegDesc.IsInt32Color()) 430// *frame = vertex.fragColor[0].u[0]; 431// else if (outputRegDesc.IsVectorType(Float)) 432 { 433 Vec4<BlendComp_t> src; 434 RGBAFloatx4ToRGBAIntx4(&vertex.fragColor[0], &src); 435 Saturate(&src); 436 *frame = RGBAIntx4ToRGBAInt(&src); 437 } 438// else if (outputRegDesc.IsVectorType(Fixed16)) 439// { 440// Vec4<BlendComp_t> & src = (Vec4<BlendComp_t> &)vertex.fragColor[0]; 441// src.r = (src.r * 255 >> 16); 442// src.g = (src.g * 255 >> 16); 443// src.b = (src.b * 255 >> 16); 444// src.a = (src.a * 255 >> 16); 445// Saturate(&src); 446// *frame = RGBAIntx4ToRGBAInt(&src); 447// } 448// else if (outputRegDesc.IsVectorType(Fixed8)) 449// { 450// Vec4<BlendComp_t> & src = (Vec4<BlendComp_t> &)vertex.fragColor[0]; 451// Saturate(&src); 452// *frame = RGBAIntx4ToRGBAInt(&src); 453// } 454// else 455// assert(0); 456 } 457 458 if (DepthWrite) 459 *depth = z; 460 if (StencilTest) 461 *stencil = StencilOp(sdPass, s, sRef); 462 } else if (StencilTest) 463 *stencil = StencilOp(sdFail, s, sRef); 464 } else if (StencilTest) 465 *stencil = StencilOp(ssFail, s, sRef); 466 467 frame++; 468 depth++; 469 stencil++; 470 471#if USE_FORCED_FIXEDPOINT 472 for (unsigned j = 0; j < 4; j++) { 473 if (ctx->glCtx->Shader.CurrentProgram->FragmentProgram->UsesFragCoord) 474 vertex.position.i[j] += vertexDx.position.i[j]; 475 for (unsigned i = 0; i < varyingCount; i++) 476 vertex.varyings[i].i[j] += vertexDx.varyings[i].i[j]; 477 } 478 vertex.position.i[2] += vertexDx.position.i[2]; 479 if (ctx->glCtx->Shader.CurrentProgram->FragmentProgram->UsesPointCoord) { 480 vertex.frontFacingPointCoord.i[2] = vertexDx.frontFacingPointCoord.i[2]; 481 vertex.frontFacingPointCoord.i[3] = vertexDx.frontFacingPointCoord.i[3]; 482 } 483#else 484 if (ctx->glCtx->CurrentProgram->UsesFragCoord) 485 vertex.position += vertexDx.position; 486 else if (ctx->bufferState.depthTest) 487 vertex.position.z += vertexDx.position.z; 488 489 for (unsigned i = 0; i < varyingCount; i++) 490 vertex.varyings[i] += vertexDx.varyings[i]; 491 if (ctx->glCtx->CurrentProgram->UsesPointCoord) 492 { 493 vertex.frontFacingPointCoord.z += vertexDx.frontFacingPointCoord.z; 494 vertex.frontFacingPointCoord.w += vertexDx.frontFacingPointCoord.w; 495 } 496#endif // #if USE_FORCED_FIXEDPOINT 497 } 498 499#endif // #if USE_LLVM_SCANLINE 500 501#if !USE_LLVM_TEXTURE_SAMPLER 502 textureGGLContext = NULL; 503#endif 504} 505 506static void PickScanLine(GGLInterface * iface) 507{ 508 GGL_GET_CONTEXT(ctx, iface); 509 510 ctx->interface.ScanLine = NULL; 511 if (ctx->bufferState.stencilTest) { 512 if (ctx->bufferState.depthTest) { 513 if (ctx->blendState.enable) 514 ctx->interface.ScanLine = ScanLine<true, true, true, true>; 515 else 516 ctx->interface.ScanLine = ScanLine<true, true, true, false>; 517 } else { 518 if (ctx->blendState.enable) 519 ctx->interface.ScanLine = ScanLine<true, false, false, true>; 520 else 521 ctx->interface.ScanLine = ScanLine<true, false, false, false>; 522 } 523 } else { 524 if (ctx->bufferState.depthTest) { 525 if (ctx->blendState.enable) 526 ctx->interface.ScanLine = ScanLine<false, true, true, true>; 527 else 528 ctx->interface.ScanLine = ScanLine<false, true, true, false>; 529 } else { 530 if (ctx->blendState.enable) 531 ctx->interface.ScanLine = ScanLine<false, false, false, true>; 532 else 533 ctx->interface.ScanLine = ScanLine<false, false, false, false>; 534 } 535 } 536 537 assert(ctx->interface.ScanLine); 538} 539 540void InitializeScanLineFunctions(GGLInterface * iface) 541{ 542 GGL_GET_CONTEXT(ctx, iface); 543 ctx->PickScanLine = PickScanLine; 544} 545