⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gglassembler.cpp

📁 Android 一些工具
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* libs/pixelflinger/codeflinger/GGLAssembler.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.*/#define LOG_TAG "GGLAssembler"#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 {// ----------------------------------------------------------------------------GGLAssembler::GGLAssembler(ARMAssemblerInterface* target)    : ARMAssemblerProxy(target), RegisterAllocator(), mOptLevel(7){}GGLAssembler::~GGLAssembler(){}void GGLAssembler::prolog(){    ARMAssemblerProxy::prolog();}void GGLAssembler::epilog(uint32_t touched){    ARMAssemblerProxy::epilog(touched);}void GGLAssembler::reset(int opt_level){    ARMAssemblerProxy::reset();    RegisterAllocator::reset();    mOptLevel = opt_level;}// ---------------------------------------------------------------------------int GGLAssembler::scanline(const needs_t& needs, context_t const* c){    int err = 0;    int opt_level = mOptLevel;    while (opt_level >= 0) {        reset(opt_level);        err = scanline_core(needs, c);        if (err == 0)            break;        opt_level--;    }        // XXX: in theory, pcForLabel is not valid before generate()    uint32_t* fragment_start_pc = pcForLabel("fragment_loop");    uint32_t* fragment_end_pc = pcForLabel("epilog");    const int per_fragment_ops = int(fragment_end_pc - fragment_start_pc);        // build a name for our pipeline    char name[64];        sprintf(name,            "scanline__%08X:%08X_%08X_%08X [%3d ipp]",            needs.p, needs.n, needs.t[0], needs.t[1], per_fragment_ops);    if (err) {        LOGE("Error while generating ""%s""\n", name);        disassemble(name);        return -1;    }    return generate(name);}int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c){    int64_t duration = ggl_system_time();    mBlendFactorCached = 0;    mBlending = 0;    mMasking = 0;    mAA        = GGL_READ_NEEDS(P_AA, needs.p);    mDithering = GGL_READ_NEEDS(P_DITHER, needs.p);    mAlphaTest = GGL_READ_NEEDS(P_ALPHA_TEST, needs.p) + GGL_NEVER;    mDepthTest = GGL_READ_NEEDS(P_DEPTH_TEST, needs.p) + GGL_NEVER;    mFog       = GGL_READ_NEEDS(P_FOG, needs.p) != 0;    mSmooth    = GGL_READ_NEEDS(SHADE, needs.n) != 0;    mBuilderContext.needs = needs;    mBuilderContext.c = c;    mBuilderContext.Rctx = reserveReg(R0); // context always in R0    mCbFormat = c->formats[ GGL_READ_NEEDS(CB_FORMAT, needs.n) ];    // ------------------------------------------------------------------------    decodeLogicOpNeeds(needs);    decodeTMUNeeds(needs, c);    mBlendSrc  = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_SRC, needs.n));    mBlendDst  = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_DST, needs.n));    mBlendSrcA = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_SRCA, needs.n));    mBlendDstA = ggl_needs_to_blendfactor(GGL_READ_NEEDS(BLEND_DSTA, needs.n));    if (!mCbFormat.c[GGLFormat::ALPHA].h) {        if ((mBlendSrc == GGL_ONE_MINUS_DST_ALPHA) ||            (mBlendSrc == GGL_DST_ALPHA)) {            mBlendSrc = GGL_ONE;        }        if ((mBlendSrcA == GGL_ONE_MINUS_DST_ALPHA) ||            (mBlendSrcA == GGL_DST_ALPHA)) {            mBlendSrcA = GGL_ONE;        }        if ((mBlendDst == GGL_ONE_MINUS_DST_ALPHA) ||            (mBlendDst == GGL_DST_ALPHA)) {            mBlendDst = GGL_ONE;        }        if ((mBlendDstA == GGL_ONE_MINUS_DST_ALPHA) ||            (mBlendDstA == GGL_DST_ALPHA)) {            mBlendDstA = GGL_ONE;        }    }    // if we need the framebuffer, read it now    const int blending =    blending_codes(mBlendSrc, mBlendDst) |                            blending_codes(mBlendSrcA, mBlendDstA);    // XXX: handle special cases, destination not modified...    if ((mBlendSrc==GGL_ZERO) && (mBlendSrcA==GGL_ZERO) &&        (mBlendDst==GGL_ONE) && (mBlendDstA==GGL_ONE)) {        // Destination unmodified (beware of logic ops)    } else if ((mBlendSrc==GGL_ZERO) && (mBlendSrcA==GGL_ZERO) &&        (mBlendDst==GGL_ZERO) && (mBlendDstA==GGL_ZERO)) {        // Destination is zero (beware of logic ops)    }        const int masking = GGL_READ_NEEDS(MASK_ARGB, needs.n);    for (int i=0 ; i<4 ; i++) {        const int mask = 1<<i;        component_info_t& info = mInfo[i];        int fs = i==GGLFormat::ALPHA ? mBlendSrcA : mBlendSrc;        int fd = i==GGLFormat::ALPHA ? mBlendDstA : mBlendDst;        if (fs==GGL_SRC_ALPHA_SATURATE && i==GGLFormat::ALPHA)            fs = GGL_ONE;        info.masked =   !!(masking & mask);        info.inDest =   !info.masked && mCbFormat.c[i].h &&                         ((mLogicOp & LOGIC_OP_SRC) || (!mLogicOp));        if (mCbFormat.components >= GGL_LUMINANCE &&                (i==GGLFormat::GREEN || i==GGLFormat::BLUE)) {            info.inDest = false;        }        info.needed =   (i==GGLFormat::ALPHA) &&                         (isAlphaSourceNeeded() || mAlphaTest != GGL_ALWAYS);        info.replaced = !!(mTextureMachine.replaced & mask);        info.iterated = (!info.replaced && (info.inDest || info.needed));         info.smooth =   mSmooth && info.iterated;        info.fog =      mFog && info.inDest && (i != GGLFormat::ALPHA);        info.blend =    (fs != int(GGL_ONE)) || (fd > int(GGL_ZERO));        mBlending |= (info.blend ? mask : 0);        mMasking |= (mCbFormat.c[i].h && info.masked) ? mask : 0;    }    fragment_parts_t parts;    // ------------------------------------------------------------------------    prolog();    // ------------------------------------------------------------------------    build_scanline_prolog(parts, needs);    if (registerFile().status())        return registerFile().status();    // ------------------------------------------------------------------------    label("fragment_loop");    // ------------------------------------------------------------------------    {        Scratch regs(registerFile());        if (mDithering) {            // update the dither index.            MOV(AL, 0, parts.count.reg,                    reg_imm(parts.count.reg, ROR, GGL_DITHER_ORDER_SHIFT));            ADD(AL, 0, parts.count.reg, parts.count.reg,                    imm( 1 << (32 - GGL_DITHER_ORDER_SHIFT)));            MOV(AL, 0, parts.count.reg,                    reg_imm(parts.count.reg, ROR, 32 - GGL_DITHER_ORDER_SHIFT));        }        // XXX: could we do an early alpha-test here in some cases?        // It would probaly be used only with smooth-alpha and no texture        // (or no alpha component in the texture).        // Early z-test        if (mAlphaTest==GGL_ALWAYS) {            build_depth_test(parts, Z_TEST|Z_WRITE);        } else {            // we cannot do the z-write here, because            // it might be killed by the alpha-test later            build_depth_test(parts, Z_TEST);        }        { // texture coordinates            Scratch scratches(registerFile());            // texel generation            build_textures(parts, regs);        }                if ((blending & (FACTOR_DST|BLEND_DST)) || mMasking ||                (mLogicOp & LOGIC_OP_DST)) {            // blending / logic_op / masking need the framebuffer            mDstPixel.setTo(regs.obtain(), &mCbFormat);            // load the framebuffer pixel            comment("fetch color-buffer");            load(parts.cbPtr, mDstPixel);        }        if (registerFile().status())            return registerFile().status();        pixel_t pixel;        int directTex = mTextureMachine.directTexture;        if (directTex | parts.packed) {            // note: we can't have both here            // iterated color or direct texture            pixel = directTex ? parts.texel[directTex-1] : parts.iterated;            pixel.flags &= ~CORRUPTIBLE;        } else {            if (mDithering) {                const int ctxtReg = mBuilderContext.Rctx;                const int mask = GGL_DITHER_SIZE-1;                parts.dither = reg_t(regs.obtain());                AND(AL, 0, parts.dither.reg, parts.count.reg, imm(mask));                ADD(AL, 0, parts.dither.reg, parts.dither.reg, ctxtReg);                LDRB(AL, parts.dither.reg, parts.dither.reg,                        immed12_pre(GGL_OFFSETOF(ditherMatrix)));            }                    // allocate a register for the resulting pixel            pixel.setTo(regs.obtain(), &mCbFormat, FIRST);            build_component(pixel, parts, GGLFormat::ALPHA,    regs);            if (mAlphaTest!=GGL_ALWAYS) {                // only handle the z-write part here. We know z-test                // was successful, as well as alpha-test.                build_depth_test(parts, Z_WRITE);            }            build_component(pixel, parts, GGLFormat::RED,      regs);            build_component(pixel, parts, GGLFormat::GREEN,    regs);            build_component(pixel, parts, GGLFormat::BLUE,     regs);            pixel.flags |= CORRUPTIBLE;        }        if (registerFile().status())            return registerFile().status();                if (pixel.reg == -1) {            // be defensive here. if we're here it's probably            // that this whole fragment is a no-op.            pixel = mDstPixel;        }                // logic operation        build_logic_op(pixel, regs);        // masking        build_masking(pixel, regs);         comment("store");        store(parts.cbPtr, pixel, WRITE_BACK);    }    if (registerFile().status())        return registerFile().status();    // update the iterated color...    if (parts.reload != 3) {        build_smooth_shade(parts);    }    // update iterated z    build_iterate_z(parts);    // update iterated fog    build_iterate_f(parts);    SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16));    B(PL, "fragment_loop");    label("epilog");    epilog(registerFile().touched());    if ((mAlphaTest!=GGL_ALWAYS) || (mDepthTest!=GGL_ALWAYS)) {        if (mDepthTest!=GGL_ALWAYS) {            label("discard_before_textures");            build_iterate_texture_coordinates(parts);        }        label("discard_after_textures");        build_smooth_shade(parts);        build_iterate_z(parts);        build_iterate_f(parts);        ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3));        SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16));        B(PL, "fragment_loop");        epilog(registerFile().touched());    }    return registerFile().status();}// ---------------------------------------------------------------------------void GGLAssembler::build_scanline_prolog(    fragment_parts_t& parts, const needs_t& needs){    Scratch scratches(registerFile());    int Rctx = mBuilderContext.Rctx;    // compute count    comment("compute ct (# of pixels to process)");    parts.count.setTo(obtainReg());    int Rx = scratches.obtain();        int Ry = scratches.obtain();    CONTEXT_LOAD(Rx, iterators.xl);    CONTEXT_LOAD(parts.count.reg, iterators.xr);    CONTEXT_LOAD(Ry, iterators.y);    // parts.count = iterators.xr - Rx    SUB(AL, 0, parts.count.reg, parts.count.reg, Rx);    SUB(AL, 0, parts.count.reg, parts.count.reg, imm(1));    if (mDithering) {        // parts.count.reg = 0xNNNNXXDD        // NNNN = count-1        // DD   = dither offset        // XX   = 0xxxxxxx (x = garbage)        Scratch scratches(registerFile());        int tx = scratches.obtain();        int ty = scratches.obtain();        AND(AL, 0, tx, Rx, imm(GGL_DITHER_MASK));        AND(AL, 0, ty, Ry, imm(GGL_DITHER_MASK));        ADD(AL, 0, tx, tx, reg_imm(ty, LSL, GGL_DITHER_ORDER_SHIFT));        ORR(AL, 0, parts.count.reg, tx, reg_imm(parts.count.reg, LSL, 16));    } else {        // parts.count.reg = 0xNNNN0000        // NNNN = count-1        MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, LSL, 16));    }    // compute dst ptr    comment("compute color-buffer pointer");    const int cb_bits = mCbFormat.size*8;    int Rs = scratches.obtain();    parts.cbPtr.setTo(obtainReg(), cb_bits);    CONTEXT_LOAD(Rs, state.buffers.color.stride);    CONTEXT_LOAD(parts.cbPtr.reg, state.buffers.color.data);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -