📄 texturing.cpp
字号:
/* libs/pixelflinger/codeflinger/texturing.cpp**** Copyright 2006, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at **** http://www.apache.org/licenses/LICENSE-2.0 **** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License.*/#include <assert.h>#include <stdint.h>#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <cutils/log.h>#include "codeflinger/GGLAssembler.h"namespace android {// ---------------------------------------------------------------------------// iterators are initialized like this:// (intToFixedCenter(x) * dx)>>16 + x0// ((x<<16 + 0x8000) * dx)>>16 + x0// ((x<<16)*dx + (0x8000*dx))>>16 + x0// ( (x*dx) + dx>>1 ) + x0// (x*dx) + (dx>>1 + x0)void GGLAssembler::init_iterated_color(fragment_parts_t& parts, const reg_t& x){ context_t const* c = mBuilderContext.c; const needs_t& needs = mBuilderContext.needs; if (mSmooth) { // NOTE: we could take this case in the mDithering + !mSmooth case, // but this would use up to 4 more registers for the color components // for only a little added quality. // Currently, this causes the system to run out of registers in // some case (see issue #719496) comment("compute initial iterated color (smooth and/or dither case)"); parts.iterated_packed = 0; parts.packed = 0; // 0x1: color component // 0x2: iterators const int optReload = mOptLevel >> 1; if (optReload >= 3) parts.reload = 0; // reload nothing else if (optReload == 2) parts.reload = 2; // reload iterators else if (optReload == 1) parts.reload = 1; // reload colors else if (optReload <= 0) parts.reload = 3; // reload both if (!mSmooth) { // we're not smoothing (just dithering), we never have to // reload the iterators parts.reload &= ~2; } Scratch scratches(registerFile()); const int t0 = (parts.reload & 1) ? scratches.obtain() : 0; const int t1 = (parts.reload & 2) ? scratches.obtain() : 0; for (int i=0 ; i<4 ; i++) { if (!mInfo[i].iterated) continue; // this component exists in the destination and is not replaced // by a texture unit. const int c = (parts.reload & 1) ? t0 : obtainReg(); if (i==0) CONTEXT_LOAD(c, iterators.ydady); if (i==1) CONTEXT_LOAD(c, iterators.ydrdy); if (i==2) CONTEXT_LOAD(c, iterators.ydgdy); if (i==3) CONTEXT_LOAD(c, iterators.ydbdy); parts.argb[i].reg = c; if (mInfo[i].smooth) { parts.argb_dx[i].reg = (parts.reload & 2) ? t1 : obtainReg(); const int dvdx = parts.argb_dx[i].reg; CONTEXT_LOAD(dvdx, generated_vars.argb[i].dx); MLA(AL, 0, c, x.reg, dvdx, c); // adjust the color iterator to make sure it won't overflow if (!mAA) { // this is not needed when we're using anti-aliasing // because we will (have to) clamp the components // anyway. int end = scratches.obtain(); MOV(AL, 0, end, reg_imm(parts.count.reg, LSR, 16)); MLA(AL, 1, end, dvdx, end, c); SUB(MI, 0, c, c, end); BIC(AL, 0, c, c, reg_imm(c, ASR, 31)); scratches.recycle(end); } } if (parts.reload & 1) { CONTEXT_STORE(c, generated_vars.argb[i].c); } } } else { // We're not smoothed, so we can // just use a packed version of the color and extract the // components as needed (or not at all if we don't blend) // figure out if we need the iterated color int load = 0; for (int i=0 ; i<4 ; i++) { component_info_t& info = mInfo[i]; if ((info.inDest || info.needed) && !info.replaced) load |= 1; } parts.iterated_packed = 1; parts.packed = (!mTextureMachine.mask && !mBlending && !mFog && !mDithering); parts.reload = 0; if (load || parts.packed) { if (mBlending || mDithering || mInfo[GGLFormat::ALPHA].needed) { comment("load initial iterated color (8888 packed)"); parts.iterated.setTo(obtainReg(), &(c->formats[GGL_PIXEL_FORMAT_RGBA_8888])); CONTEXT_LOAD(parts.iterated.reg, packed8888); } else { comment("load initial iterated color (dest format packed)"); parts.iterated.setTo(obtainReg(), &mCbFormat); // pre-mask the iterated color const int bits = parts.iterated.size(); const uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1; uint32_t mask = 0; if (mMasking) { for (int i=0 ; i<4 ; i++) { const int component_mask = 1<<i; const int h = parts.iterated.format.c[i].h; const int l = parts.iterated.format.c[i].l; if (h && (!(mMasking & component_mask))) { mask |= ((1<<(h-l))-1) << l; } } } if (mMasking && ((mask & size)==0)) { // none of the components are present in the mask } else { CONTEXT_LOAD(parts.iterated.reg, packed); if (mCbFormat.size == 1) { AND(AL, 0, parts.iterated.reg, parts.iterated.reg, imm(0xFF)); } else if (mCbFormat.size == 2) { MOV(AL, 0, parts.iterated.reg, reg_imm(parts.iterated.reg, LSR, 16)); } } // pre-mask the iterated color if (mMasking) { build_and_immediate(parts.iterated.reg, parts.iterated.reg, mask, bits); } } } }}void GGLAssembler::build_iterated_color( component_t& fragment, const fragment_parts_t& parts, int component, Scratch& regs){ fragment.setTo( regs.obtain(), 0, 32, CORRUPTIBLE); if (!mInfo[component].iterated) return; if (parts.iterated_packed) { // iterated colors are packed, extract the one we need extract(fragment, parts.iterated, component); } else { fragment.h = GGL_COLOR_BITS; fragment.l = GGL_COLOR_BITS - 8; fragment.flags |= CLEAR_LO; // iterated colors are held in their own register, // (smooth and/or dithering case) if (parts.reload==3) { // this implies mSmooth Scratch scratches(registerFile()); int dx = scratches.obtain(); CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c); CONTEXT_LOAD(dx, generated_vars.argb[component].dx); ADD(AL, 0, dx, fragment.reg, dx); CONTEXT_STORE(dx, generated_vars.argb[component].c); } else if (parts.reload & 1) { CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c); } else { // we don't reload, so simply rename the register and mark as // non CORRUPTIBLE so that the texture env or blending code // won't modify this (renamed) register regs.recycle(fragment.reg); fragment.reg = parts.argb[component].reg; fragment.flags &= ~CORRUPTIBLE; } if (mInfo[component].smooth && mAA) { // when using smooth shading AND anti-aliasing, we need to clamp // the iterators because there is always an extra pixel on the // edges, which most of the time will cause an overflow // (since technically its outside of the domain). BIC(AL, 0, fragment.reg, fragment.reg, reg_imm(fragment.reg, ASR, 31)); component_sat(fragment); } }}// ---------------------------------------------------------------------------void GGLAssembler::decodeLogicOpNeeds(const needs_t& needs){ // gather some informations about the components we need to process... const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR; switch(opcode) { case GGL_COPY: mLogicOp = 0; break; case GGL_CLEAR: case GGL_SET: mLogicOp = LOGIC_OP; break; case GGL_AND: case GGL_AND_REVERSE: case GGL_AND_INVERTED: case GGL_XOR: case GGL_OR: case GGL_NOR: case GGL_EQUIV: case GGL_OR_REVERSE: case GGL_OR_INVERTED: case GGL_NAND: mLogicOp = LOGIC_OP|LOGIC_OP_SRC|LOGIC_OP_DST; break; case GGL_NOOP: case GGL_INVERT: mLogicOp = LOGIC_OP|LOGIC_OP_DST; break; case GGL_COPY_INVERTED: mLogicOp = LOGIC_OP|LOGIC_OP_SRC; break; }; }void GGLAssembler::decodeTMUNeeds(const needs_t& needs, context_t const* c){ uint8_t replaced=0; mTextureMachine.mask = 0; mTextureMachine.activeUnits = 0; for (int i=GGL_TEXTURE_UNIT_COUNT-1 ; i>=0 ; i--) { texture_unit_t& tmu = mTextureMachine.tmu[i]; if (replaced == 0xF) { // all components are replaced, skip this TMU. tmu.format_idx = 0; tmu.mask = 0; tmu.replaced = replaced; continue; } tmu.format_idx = GGL_READ_NEEDS(T_FORMAT, needs.t[i]); tmu.format = c->formats[tmu.format_idx]; tmu.bits = tmu.format.size*8; tmu.swrap = GGL_READ_NEEDS(T_S_WRAP, needs.t[i]); tmu.twrap = GGL_READ_NEEDS(T_T_WRAP, needs.t[i]); tmu.env = ggl_needs_to_env(GGL_READ_NEEDS(T_ENV, needs.t[i])); tmu.pot = GGL_READ_NEEDS(T_POT, needs.t[i]); tmu.linear = GGL_READ_NEEDS(T_LINEAR, needs.t[i]) && tmu.format.size!=3; // XXX: only 8, 16 and 32 modes for now // 5551 linear filtering is not supported if (tmu.format_idx == GGL_PIXEL_FORMAT_RGBA_5551) tmu.linear = 0; tmu.mask = 0; tmu.replaced = replaced; if (tmu.format_idx) { mTextureMachine.activeUnits++; if (tmu.format.c[0].h) tmu.mask |= 0x1; if (tmu.format.c[1].h) tmu.mask |= 0x2; if (tmu.format.c[2].h) tmu.mask |= 0x4; if (tmu.format.c[3].h) tmu.mask |= 0x8; if (tmu.env == GGL_REPLACE) { replaced |= tmu.mask; } else if (tmu.env == GGL_DECAL) { if (!tmu.format.c[GGLFormat::ALPHA].h) { // if we don't have alpha, decal does nothing tmu.mask = 0; } else { // decal always ignores At tmu.mask &= ~(1<<GGLFormat::ALPHA); } } } mTextureMachine.mask |= tmu.mask; //printf("%d: mask=%08lx, replaced=%08lx\n", // i, int(tmu.mask), int(tmu.replaced)); } mTextureMachine.replaced = replaced; mTextureMachine.directTexture = 0; //printf("replaced=%08lx\n", mTextureMachine.replaced);}void GGLAssembler::init_textures( tex_coord_t* coords, const reg_t& x, const reg_t& y){ context_t const* c = mBuilderContext.c; const needs_t& needs = mBuilderContext.needs; int Rctx = mBuilderContext.Rctx; int Rx = x.reg; int Ry = y.reg; if (mTextureMachine.mask) { comment("compute texture coordinates"); } // init texture coordinates for each tmu const int cb_format_idx = GGL_READ_NEEDS(CB_FORMAT, needs.n); const bool multiTexture = mTextureMachine.activeUnits > 1; for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) { const texture_unit_t& tmu = mTextureMachine.tmu[i]; if (tmu.format_idx == 0) continue; if ((tmu.swrap == GGL_NEEDS_WRAP_11) && (tmu.twrap == GGL_NEEDS_WRAP_11)) { // 1:1 texture pointer_t& txPtr = coords[i].ptr; txPtr.setTo(obtainReg(), tmu.bits); CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydsdy); ADD(AL, 0, Rx, Rx, reg_imm(txPtr.reg, ASR, 16)); // x += (s>>16) CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydtdy); ADD(AL, 0, Ry, Ry, reg_imm(txPtr.reg, ASR, 16)); // y += (t>>16) // merge base & offset CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].stride); SMLABB(AL, Rx, Ry, txPtr.reg, Rx); // x+y*stride CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data); base_offset(txPtr, txPtr, Rx); } else { Scratch scratches(registerFile()); reg_t& s = coords[i].s; reg_t& t = coords[i].t; // s = (x * dsdx)>>16 + ydsdy // s = (x * dsdx)>>16 + (y*dsdy)>>16 + s0 // t = (x * dtdx)>>16 + ydtdy // t = (x * dtdx)>>16 + (y*dtdy)>>16 + t0 s.setTo(obtainReg()); t.setTo(obtainReg()); const int need_w = GGL_READ_NEEDS(W, needs.n); if (need_w) { CONTEXT_LOAD(s.reg, state.texture[i].iterators.ydsdy); CONTEXT_LOAD(t.reg, state.texture[i].iterators.ydtdy); } else { int ydsdy = scratches.obtain(); int ydtdy = scratches.obtain(); CONTEXT_LOAD(s.reg, generated_vars.texture[i].dsdx); CONTEXT_LOAD(ydsdy, state.texture[i].iterators.ydsdy); CONTEXT_LOAD(t.reg, generated_vars.texture[i].dtdx); CONTEXT_LOAD(ydtdy, state.texture[i].iterators.ydtdy); MLA(AL, 0, s.reg, Rx, s.reg, ydsdy); MLA(AL, 0, t.reg, Rx, t.reg, ydtdy); } if ((mOptLevel&1)==0) { CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]); CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]); recycleReg(s.reg); recycleReg(t.reg); } } // direct texture? if (!multiTexture && !mBlending && !mDithering && !mFog && cb_format_idx == tmu.format_idx && !tmu.linear && mTextureMachine.replaced == tmu.mask) { mTextureMachine.directTexture = i + 1; } }}void GGLAssembler::build_textures( fragment_parts_t& parts, Scratch& regs){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -