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

📄 scanline.cpp

📁 Android 一些工具
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* libs/pixelflinger/scanline.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 "pixelflinger"#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <cutils/memory.h>#include <cutils/log.h>#include "buffer.h"#include "scanline.h"#include "codeflinger/CodeCache.h"#include "codeflinger/GGLAssembler.h"#include "codeflinger/ARMAssembler.h"//#include "codeflinger/ARMAssemblerOptimizer.h"// ----------------------------------------------------------------------------#define ANDROID_CODEGEN_GENERIC     0   // force generic pixel pipeline#define ANDROID_CODEGEN_C           1   // hand-written C, fallback generic #define ANDROID_CODEGEN_ASM         2   // hand-written asm, fallback generic#define ANDROID_CODEGEN_GENERATED   3   // hand-written asm, fallback codegen#ifdef NDEBUG#   define ANDROID_RELEASE#   define ANDROID_CODEGEN      ANDROID_CODEGEN_GENERATED#else#   define ANDROID_DEBUG#   define ANDROID_CODEGEN      ANDROID_CODEGEN_GENERATED#endif#if defined(__arm__)#   define ANDROID_ARM_CODEGEN  1#else#   define ANDROID_ARM_CODEGEN  0#endif#define DEBUG__CODEGEN_ONLY     0// ----------------------------------------------------------------------------namespace android {// ----------------------------------------------------------------------------static void init_y(context_t*, int32_t);static void init_y_noop(context_t*, int32_t);static void init_y_packed(context_t*, int32_t);static void init_y_error(context_t*, int32_t);static void step_y__generic(context_t* c);static void step_y__nop(context_t*);static void step_y__smooth(context_t* c);static void step_y__tmu(context_t* c);static void step_y__w(context_t* c);static void scanline(context_t* c);static void scanline_perspective(context_t* c);static void scanline_perspective_single(context_t* c);static void scanline_t32cb16blend(context_t* c);static void scanline_t32cb16(context_t* c);static void scanline_memcpy(context_t* c);static void scanline_memset8(context_t* c);static void scanline_memset16(context_t* c);static void scanline_memset32(context_t* c);static void scanline_noop(context_t* c);static void scanline_set(context_t* c);static void scanline_clear(context_t* c);static void rect_generic(context_t* c, size_t yc);static void rect_memcpy(context_t* c, size_t yc);extern "C" void scanline_t32cb16blend_arm(uint16_t*, uint32_t*, size_t);extern "C" void scanline_t32cb16_arm(uint16_t *dst, uint32_t *src, size_t ct);// ----------------------------------------------------------------------------struct shortcut_t {    needs_filter_t  filter;    const char*     desc;    void            (*scanline)(context_t*);    void            (*init_y)(context_t*, int32_t);};// Keep in sync with needsstatic shortcut_t shortcuts[] = {    { { { 0x03515104, 0x00000077, { 0x00000A01, 0x00000000 } },        { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } },        "565 fb, 8888 tx, blend", scanline_t32cb16blend, init_y_noop },    { { { 0x03010104, 0x00000077, { 0x00000A01, 0x00000000 } },        { 0xFFFFFFFF, 0xFFFFFFFF, { 0xFFFFFFFF, 0x0000003F } } },        "565 fb, 8888 tx", scanline_t32cb16, init_y_noop  },      { { { 0x00000000, 0x00000000, { 0x00000000, 0x00000000 } },        { 0x00000000, 0x00000007, { 0x00000000, 0x00000000 } } },        "(nop) alpha test", scanline_noop, init_y_noop },    { { { 0x00000000, 0x00000000, { 0x00000000, 0x00000000 } },        { 0x00000000, 0x00000070, { 0x00000000, 0x00000000 } } },        "(nop) depth test", scanline_noop, init_y_noop },    { { { 0x05000000, 0x00000000, { 0x00000000, 0x00000000 } },        { 0x0F000000, 0x00000080, { 0x00000000, 0x00000000 } } },        "(nop) logic_op", scanline_noop, init_y_noop },    { { { 0xF0000000, 0x00000000, { 0x00000000, 0x00000000 } },        { 0xF0000000, 0x00000080, { 0x00000000, 0x00000000 } } },        "(nop) color mask", scanline_noop, init_y_noop },    { { { 0x0F000000, 0x00000077, { 0x00000000, 0x00000000 } },        { 0xFF000000, 0x000000F7, { 0x00000000, 0x00000000 } } },        "(set) logic_op", scanline_set, init_y_noop },    { { { 0x00000000, 0x00000077, { 0x00000000, 0x00000000 } },        { 0xFF000000, 0x000000F7, { 0x00000000, 0x00000000 } } },        "(clear) logic_op", scanline_clear, init_y_noop },    { { { 0x03000000, 0x00000077, { 0x00000000, 0x00000000 } },        { 0xFFFFFF00, 0x000000F7, { 0x00000000, 0x00000000 } } },        "(clear) blending 0/0", scanline_clear, init_y_noop },    { { { 0x00000000, 0x00000000, { 0x00000000, 0x00000000 } },        { 0x0000003F, 0x00000000, { 0x00000000, 0x00000000 } } },        "(error) invalid color-buffer format", scanline_noop, init_y_error },};static const needs_filter_t noblend1to1 = {        // (disregard dithering, see below)        { 0x03010100, 0x00000077, { 0x00000A00, 0x00000000 } },        { 0xFFFFFFC0, 0xFFFFFEFF, { 0xFFFFFFC0, 0x0000003F } }};static  const needs_filter_t fill16noblend = {        { 0x03010100, 0x00000077, { 0x00000000, 0x00000000 } },        { 0xFFFFFFC0, 0xFFFFFFFF, { 0x0000003F, 0x0000003F } }};// ----------------------------------------------------------------------------#if ANDROID_ARM_CODEGENstatic CodeCache gCodeCache(12 * 1024);class ScanlineAssembly : public Assembly {    AssemblyKey<needs_t> mKey;public:    ScanlineAssembly(needs_t needs, size_t size)        : Assembly(size), mKey(needs) { }    const AssemblyKey<needs_t>& key() const { return mKey; }};#endif// ----------------------------------------------------------------------------void ggl_init_scanline(context_t* c){    c->init_y = init_y;    c->step_y = step_y__generic;    c->scanline = scanline;}void ggl_uninit_scanline(context_t* c){    if (c->state.buffers.coverage)        free(c->state.buffers.coverage);#if ANDROID_ARM_CODEGEN    if (c->scanline_as)        c->scanline_as->decStrong(c);#endif}// ----------------------------------------------------------------------------static void pick_scanline(context_t* c){#if (!defined(DEBUG__CODEGEN_ONLY) || (DEBUG__CODEGEN_ONLY == 0))#if ANDROID_CODEGEN == ANDROID_CODEGEN_GENERIC    c->init_y = init_y;    c->step_y = step_y__generic;    c->scanline = scanline;    return;#endif    //printf("*** needs [%08lx:%08lx:%08lx:%08lx]\n",    //    c->state.needs.n, c->state.needs.p,    //    c->state.needs.t[0], c->state.needs.t[1]);    // first handle the special case that we cannot test with a filter    const uint32_t cb_format = GGL_READ_NEEDS(CB_FORMAT, c->state.needs.n);    if (GGL_READ_NEEDS(T_FORMAT, c->state.needs.t[0]) == cb_format) {        if (c->state.needs.match(noblend1to1)) {            // this will match regardless of dithering state, since both            // src and dest have the same format anyway, there is no dithering            // to be done.            const GGLFormat* f =                &(c->formats[GGL_READ_NEEDS(T_FORMAT, c->state.needs.t[0])]);            if ((f->components == GGL_RGB) ||                (f->components == GGL_RGBA) ||                (f->components == GGL_LUMINANCE) ||                (f->components == GGL_LUMINANCE_ALPHA))            {                // format must have all of RGB components                // (so the current color doesn't show through)                c->scanline = scanline_memcpy;                c->init_y = init_y_noop;                return;            }        }    }    if (c->state.needs.match(fill16noblend)) {        c->init_y = init_y_packed;        switch (c->formats[cb_format].size) {        case 1: c->scanline = scanline_memset8;  return;        case 2: c->scanline = scanline_memset16; return;        case 4: c->scanline = scanline_memset32; return;        }    }    const int numFilters = sizeof(shortcuts)/sizeof(shortcut_t);    for (int i=0 ; i<numFilters ; i++) {        if (c->state.needs.match(shortcuts[i].filter)) {            c->scanline = shortcuts[i].scanline;            c->init_y = shortcuts[i].init_y;            return;        }    }#endif // DEBUG__CODEGEN_ONLY    c->init_y = init_y;    c->step_y = step_y__generic;#if ANDROID_ARM_CODEGEN    // we're going to have to generate some code...    // here, generate code for our pixel pipeline    const AssemblyKey<needs_t> key(c->state.needs);    sp<Assembly> assembly = gCodeCache.lookup(key);    if (assembly == 0) {        // create a new assembly region        sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs, 1024);        // initialize our assembler        GGLAssembler assembler( new ARMAssembler(a) );        //GGLAssembler assembler(        //        new ARMAssemblerOptimizer(new ARMAssembler(a)) );        // generate the scanline code for the given needs        int err = assembler.scanline(c->state.needs, c);        if (ggl_likely(!err)) {            // finally, cache this assembly            err = gCodeCache.cache(a->key(), a);        }        if (ggl_unlikely(err)) {            LOGE("error generating or caching assembly. Reverting to NOP.");            c->scanline = scanline_noop;            c->init_y = init_y_noop;            c->step_y = step_y__nop;            return;        }        assembly = a;    }    // release the previous assembly    if (c->scanline_as) {        c->scanline_as->decStrong(c);    }    //LOGI("using generated pixel-pipeline");    c->scanline_as = assembly.get();    c->scanline_as->incStrong(c); //  hold on to assembly    c->scanline = (void(*)(context_t* c))assembly->base();#else//    LOGW("using generic (slow) pixel-pipeline");    c->scanline = scanline;#endif}void ggl_pick_scanline(context_t* c){    pick_scanline(c);    if ((c->state.enables & GGL_ENABLE_W) &&        (c->state.enables & GGL_ENABLE_TMUS))    {        c->span = c->scanline;        c->scanline = scanline_perspective;        if (!(c->state.enabled_tmu & (c->state.enabled_tmu - 1))) {            // only one TMU enabled            c->scanline = scanline_perspective_single;        }    }}// ----------------------------------------------------------------------------static void blending(context_t* c, pixel_t* fragment, pixel_t* fb);static void blend_factor(context_t* c, pixel_t* r, uint32_t factor,        const pixel_t* src, const pixel_t* dst);static void rescale(uint32_t& u, uint8_t& su, uint32_t& v, uint8_t& sv);#if ANDROID_ARM_CODEGEN && (ANDROID_CODEGEN == ANDROID_CODEGEN_GENERATED)// no need to compile the generic-pipeline, it can't be reachedvoid scanline(context_t*){}#elsevoid rescale(uint32_t& u, uint8_t& su, uint32_t& v, uint8_t& sv){    if (su && sv) {        if (su > sv) {            v = ggl_expand(v, sv, su);            sv = su;        } else if (su < sv) {            u = ggl_expand(u, su, sv);            su = sv;        }    }}void blending(context_t* c, pixel_t* fragment, pixel_t* fb){    rescale(fragment->c[0], fragment->s[0], fb->c[0], fb->s[0]);    rescale(fragment->c[1], fragment->s[1], fb->c[1], fb->s[1]);    rescale(fragment->c[2], fragment->s[2], fb->c[2], fb->s[2]);    rescale(fragment->c[3], fragment->s[3], fb->c[3], fb->s[3]);    pixel_t sf, df;    blend_factor(c, &sf, c->state.blend.src, fragment, fb);    blend_factor(c, &df, c->state.blend.dst, fragment, fb);    fragment->c[1] =            gglMulAddx(fragment->c[1], sf.c[1], gglMulx(fb->c[1], df.c[1]));    fragment->c[2] =            gglMulAddx(fragment->c[2], sf.c[2], gglMulx(fb->c[2], df.c[2]));    fragment->c[3] =            gglMulAddx(fragment->c[3], sf.c[3], gglMulx(fb->c[3], df.c[3]));    if (c->state.blend.alpha_separate) {        blend_factor(c, &sf, c->state.blend.src_alpha, fragment, fb);        blend_factor(c, &df, c->state.blend.dst_alpha, fragment, fb);    }    fragment->c[0] =            gglMulAddx(fragment->c[0], sf.c[0], gglMulx(fb->c[0], df.c[0]));    // clamp to 1.0    if (fragment->c[0] >= (1LU<<fragment->s[0]))        fragment->c[0] = (1<<fragment->s[0])-1;    if (fragment->c[1] >= (1LU<<fragment->s[1]))        fragment->c[1] = (1<<fragment->s[1])-1;    if (fragment->c[2] >= (1LU<<fragment->s[2]))        fragment->c[2] = (1<<fragment->s[2])-1;    if (fragment->c[3] >= (1LU<<fragment->s[3]))        fragment->c[3] = (1<<fragment->s[3])-1;}static inline int blendfactor(uint32_t x, uint32_t size, uint32_t def = 0){    if (!size)        return def;    // scale to 16 bits

⌨️ 快捷键说明

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