📄 scanline.cpp
字号:
s = 16; } } // blending if (enables & GGL_ENABLE_BLENDING) { fb.c[1] = fb.c[2] = fb.c[3] = fb.c[0] = 0; // placate valgrind fb.s[1] = fb.s[2] = fb.s[3] = fb.s[0] = 0; c->state.buffers.color.read( &(c->state.buffers.color), c, x, y, &fb); blending( c, &fragment, &fb ); } // write c->state.buffers.color.write( &(c->state.buffers.color), c, x, y, &fragment); }discard: // iterate... x += 1; if (enables & GGL_ENABLE_SMOOTH) { r += c->shade.drdx; g += c->shade.dgdx; b += c->shade.dbdx; a += c->shade.dadx; } z += c->shade.dzdx; f += c->shade.dfdx; }}#endif // ANDROID_ARM_CODEGEN && (ANDROID_CODEGEN == ANDROID_CODEGEN_GENERATED)// ----------------------------------------------------------------------------#if 0#pragma mark -#pragma mark Scanline#endiftemplate <typename T, typename U>static inline __attribute__((const))T interpolate(int y, T v0, U dvdx, U dvdy) { // interpolates in pixel's centers // v = v0 + (y + 0.5) * dvdy + (0.5 * dvdx) return (y * dvdy) + (v0 + ((dvdy + dvdx) >> 1));}// ----------------------------------------------------------------------------#if 0#pragma mark -#endifvoid init_y(context_t* c, int32_t ys){ const uint32_t enables = c->state.enables; // compute iterators... iterators_t& ci = c->iterators; // sample in the center ci.y = ys; if (enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_W|GGL_ENABLE_FOG)) { ci.ydzdy = interpolate(ys, c->shade.z0, c->shade.dzdx, c->shade.dzdy); ci.ydwdy = interpolate(ys, c->shade.w0, c->shade.dwdx, c->shade.dwdy); ci.ydfdy = interpolate(ys, c->shade.f0, c->shade.dfdx, c->shade.dfdy); } if (ggl_unlikely(enables & GGL_ENABLE_SMOOTH)) { ci.ydrdy = interpolate(ys, c->shade.r0, c->shade.drdx, c->shade.drdy); ci.ydgdy = interpolate(ys, c->shade.g0, c->shade.dgdx, c->shade.dgdy); ci.ydbdy = interpolate(ys, c->shade.b0, c->shade.dbdx, c->shade.dbdy); ci.ydady = interpolate(ys, c->shade.a0, c->shade.dadx, c->shade.dady); c->step_y = step_y__smooth; } else { ci.ydrdy = c->shade.r0; ci.ydgdy = c->shade.g0; ci.ydbdy = c->shade.b0; ci.ydady = c->shade.a0; // XXX: do only if needed, or make sure this is fast c->packed = ggl_pack_color(c, c->state.buffers.color.format, ci.ydrdy, ci.ydgdy, ci.ydbdy, ci.ydady); c->packed8888 = ggl_pack_color(c, GGL_PIXEL_FORMAT_RGBA_8888, ci.ydrdy, ci.ydgdy, ci.ydbdy, ci.ydady); } // initialize the variables we need in the shader generated_vars_t& gen = c->generated_vars; gen.argb[GGLFormat::ALPHA].c = ci.ydady; gen.argb[GGLFormat::ALPHA].dx = c->shade.dadx; gen.argb[GGLFormat::RED ].c = ci.ydrdy; gen.argb[GGLFormat::RED ].dx = c->shade.drdx; gen.argb[GGLFormat::GREEN].c = ci.ydgdy; gen.argb[GGLFormat::GREEN].dx = c->shade.dgdx; gen.argb[GGLFormat::BLUE ].c = ci.ydbdy; gen.argb[GGLFormat::BLUE ].dx = c->shade.dbdx; gen.dzdx = c->shade.dzdx; gen.f = ci.ydfdy; gen.dfdx = c->shade.dfdx; if (enables & GGL_ENABLE_TMUS) { for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { texture_t& t = c->state.texture[i]; if (!t.enable) continue; texture_iterators_t& ti = t.iterators; if (t.s_coord == GGL_ONE_TO_ONE && t.t_coord == GGL_ONE_TO_ONE) { // we need to set all of these to 0 because in some cases // step_y__generic() or step_y__tmu() will be used and // therefore will update dtdy, however, in 1:1 mode // this is always done by the scanline rasterizer. ti.dsdx = ti.dsdy = ti.dtdx = ti.dtdy = 0; ti.ydsdy = t.shade.is0; ti.ydtdy = t.shade.it0; } else { const int adjustSWrap = ((t.s_wrap==GGL_CLAMP)?0:16); const int adjustTWrap = ((t.t_wrap==GGL_CLAMP)?0:16); ti.sscale = t.shade.sscale + adjustSWrap; ti.tscale = t.shade.tscale + adjustTWrap; if (!(enables & GGL_ENABLE_W)) { // S coordinate const int32_t sscale = ti.sscale; const int32_t sy = interpolate(ys, t.shade.is0, t.shade.idsdx, t.shade.idsdy); if (sscale>=0) { ti.ydsdy= sy << sscale; ti.dsdx = t.shade.idsdx << sscale; ti.dsdy = t.shade.idsdy << sscale; } else { ti.ydsdy= sy >> -sscale; ti.dsdx = t.shade.idsdx >> -sscale; ti.dsdy = t.shade.idsdy >> -sscale; } // T coordinate const int32_t tscale = ti.tscale; const int32_t ty = interpolate(ys, t.shade.it0, t.shade.idtdx, t.shade.idtdy); if (tscale>=0) { ti.ydtdy= ty << tscale; ti.dtdx = t.shade.idtdx << tscale; ti.dtdy = t.shade.idtdy << tscale; } else { ti.ydtdy= ty >> -tscale; ti.dtdx = t.shade.idtdx >> -tscale; ti.dtdy = t.shade.idtdy >> -tscale; } } } // mirror for generated code... generated_tex_vars_t& gen = c->generated_vars.texture[i]; gen.width = t.surface.width; gen.height = t.surface.height; gen.stride = t.surface.stride; gen.data = int32_t(t.surface.data); gen.dsdx = ti.dsdx; gen.dtdx = ti.dtdx; } } // choose the y-stepper c->step_y = step_y__nop; if (enables & GGL_ENABLE_FOG) { c->step_y = step_y__generic; } else if (enables & GGL_ENABLE_TMUS) { if (enables & GGL_ENABLE_SMOOTH) { c->step_y = step_y__generic; } else if (enables & GGL_ENABLE_W) { c->step_y = step_y__w; } else { c->step_y = step_y__tmu; } } else { if (enables & GGL_ENABLE_SMOOTH) { c->step_y = step_y__smooth; } } // choose the rectangle blitter c->rect = rect_generic; if ((c->step_y == step_y__nop) && (c->scanline == scanline_memcpy)) { c->rect = rect_memcpy; }}void init_y_packed(context_t* c, int32_t y0){ uint8_t f = c->state.buffers.color.format; c->packed = ggl_pack_color(c, f, c->shade.r0, c->shade.g0, c->shade.b0, c->shade.a0); c->iterators.y = y0; c->step_y = step_y__nop; // choose the rectangle blitter c->rect = rect_generic; if (c->scanline == scanline_memcpy) { c->rect = rect_memcpy; }}void init_y_noop(context_t* c, int32_t y0){ c->iterators.y = y0; c->step_y = step_y__nop; // choose the rectangle blitter c->rect = rect_generic; if (c->scanline == scanline_memcpy) { c->rect = rect_memcpy; }}void init_y_error(context_t* c, int32_t y0){ // woooops, shoud never happen, // fail gracefully (don't display anything) init_y_noop(c, y0); LOGE("color-buffer has an invalid format!");}// ----------------------------------------------------------------------------#if 0#pragma mark -#endifvoid step_y__generic(context_t* c){ const uint32_t enables = c->state.enables; // iterate... iterators_t& ci = c->iterators; ci.y += 1; if (enables & GGL_ENABLE_SMOOTH) { ci.ydrdy += c->shade.drdy; ci.ydgdy += c->shade.dgdy; ci.ydbdy += c->shade.dbdy; ci.ydady += c->shade.dady; } const uint32_t mask = GGL_ENABLE_DEPTH_TEST | GGL_ENABLE_W | GGL_ENABLE_FOG; if (enables & mask) { ci.ydzdy += c->shade.dzdy; ci.ydwdy += c->shade.dwdy; ci.ydfdy += c->shade.dfdy; } if ((enables & GGL_ENABLE_TMUS) && (!(enables & GGL_ENABLE_W))) { for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { if (c->state.texture[i].enable) { texture_iterators_t& ti = c->state.texture[i].iterators; ti.ydsdy += ti.dsdy; ti.ydtdy += ti.dtdy; } } }}void step_y__nop(context_t* c){ c->iterators.y += 1; c->iterators.ydzdy += c->shade.dzdy;}void step_y__smooth(context_t* c){ iterators_t& ci = c->iterators; ci.y += 1; ci.ydrdy += c->shade.drdy; ci.ydgdy += c->shade.dgdy; ci.ydbdy += c->shade.dbdy; ci.ydady += c->shade.dady; ci.ydzdy += c->shade.dzdy;}void step_y__w(context_t* c){ iterators_t& ci = c->iterators; ci.y += 1; ci.ydzdy += c->shade.dzdy; ci.ydwdy += c->shade.dwdy;}void step_y__tmu(context_t* c){ iterators_t& ci = c->iterators; ci.y += 1; ci.ydzdy += c->shade.dzdy; for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { if (c->state.texture[i].enable) { texture_iterators_t& ti = c->state.texture[i].iterators; ti.ydsdy += ti.dsdy; ti.ydtdy += ti.dtdy; } }}// ----------------------------------------------------------------------------#if 0#pragma mark -#endifvoid scanline_perspective(context_t* c){ struct { union { struct { int32_t s, sq; int32_t t, tq; }; struct { int32_t v, q; } st[2]; }; } tc[GGL_TEXTURE_UNIT_COUNT] __attribute__((aligned(16))); // XXX: we should have a special case when dwdx = 0 // 32 pixels spans works okay. 16 is a lot better, // but hey, it's a software renderer... const uint32_t SPAN_BITS = 5; const uint32_t ys = c->iterators.y; const uint32_t xs = c->iterators.xl; const uint32_t x1 = c->iterators.xr; const uint32_t xc = x1 - xs; uint32_t remainder = xc & ((1<<SPAN_BITS)-1); uint32_t numSpans = xc >> SPAN_BITS; const iterators_t& ci = c->iterators; int32_t w0 = (xs * c->shade.dwdx) + ci.ydwdy; int32_t q0 = gglRecipQ(w0, 30); const int iwscale = 32 - gglClz(q0); const int32_t dwdx = c->shade.dwdx << SPAN_BITS; int32_t xl = c->iterators.xl; // We process s & t with a loop to reduce the code size // (and i-cache pressure). for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) { const texture_t& tmu = c->state.texture[i]; if (!tmu.enable) continue; int32_t s = tmu.shade.is0 + (tmu.shade.idsdy * ys) + (tmu.shade.idsdx * xs) + ((tmu.shade.idsdx + tmu.shade.idsdy)>>1); int32_t t = tmu.shade.it0 + (tmu.shade.idtdy * ys) + (tmu.shade.idtdx * xs) + ((tmu.shade.idtdx + tmu.shade.idtdy)>>1); tc[i].s = s; tc[i].t = t; tc[i].sq = gglMulx(s, q0, iwscale); tc[i].tq = gglMulx(t, q0, iwscale); } int32_t span = 0; do { int32_t w1; if (ggl_likely(numSpans)) { w1 = w0 + dwdx; } else { if (remainder) { // finish off the scanline... span = remainder; w1 = (c->shade.dwdx * span) + w0; } else { break; } } int32_t q1 = gglRecipQ(w1, 30);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -