diff options
Diffstat (limited to 'libpixelflinger/codeflinger/GGLAssembler.h')
-rw-r--r-- | libpixelflinger/codeflinger/GGLAssembler.h | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h new file mode 100644 index 0000000..d1d29f0 --- /dev/null +++ b/libpixelflinger/codeflinger/GGLAssembler.h @@ -0,0 +1,554 @@ +/* libs/pixelflinger/codeflinger/GGLAssembler.h +** +** 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. +*/ + + +#ifndef ANDROID_GGLASSEMBLER_H +#define ANDROID_GGLASSEMBLER_H + +#include <stdint.h> +#include <sys/types.h> + +#include <private/pixelflinger/ggl_context.h> + +#include "codeflinger/ARMAssemblerProxy.h" + + +namespace android { + +// ---------------------------------------------------------------------------- + +#define CONTEXT_LOAD(REG, FIELD) \ + LDR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD))) + +#define CONTEXT_STORE(REG, FIELD) \ + STR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD))) + + +class RegisterAllocator +{ +public: + class RegisterFile; + + RegisterFile& registerFile(); + int reserveReg(int reg); + int obtainReg(); + void recycleReg(int reg); + void reset(); + + class RegisterFile + { + public: + RegisterFile(); + RegisterFile(const RegisterFile& rhs); + ~RegisterFile(); + + void reset(); + + bool operator == (const RegisterFile& rhs) const; + bool operator != (const RegisterFile& rhs) const { + return !operator == (rhs); + } + + int reserve(int reg); + void reserveSeveral(uint32_t regMask); + + void recycle(int reg); + void recycleSeveral(uint32_t regMask); + + int obtain(); + inline int isUsed(int reg) const; + + bool hasFreeRegs() const; + int countFreeRegs() const; + + uint32_t touched() const; + inline uint32_t status() const { return mStatus; } + + enum { + OUT_OF_REGISTERS = 0x1 + }; + + private: + uint32_t mRegs; + uint32_t mTouched; + uint32_t mStatus; + }; + + class Scratch + { + public: + Scratch(RegisterFile& regFile) + : mRegFile(regFile), mScratch(0) { + } + ~Scratch() { + mRegFile.recycleSeveral(mScratch); + } + int obtain() { + int reg = mRegFile.obtain(); + mScratch |= 1<<reg; + return reg; + } + void recycle(int reg) { + mRegFile.recycle(reg); + mScratch &= ~(1<<reg); + } + bool isUsed(int reg) { + return (mScratch & (1<<reg)); + } + int countFreeRegs() { + return mRegFile.countFreeRegs(); + } + private: + RegisterFile& mRegFile; + uint32_t mScratch; + }; + + class Spill + { + public: + Spill(RegisterFile& regFile, ARMAssemblerInterface& gen, uint32_t reglist) + : mRegFile(regFile), mGen(gen), mRegList(reglist), mCount(0) + { + if (reglist) { + int count = 0; + while (reglist) { + count++; + reglist &= ~(1 << (31 - __builtin_clz(reglist))); + } + if (count == 1) { + int reg = 31 - __builtin_clz(mRegList); + mGen.STR(mGen.AL, reg, mGen.SP, mGen.immed12_pre(-4, 1)); + } else { + mGen.STM(mGen.AL, mGen.DB, mGen.SP, 1, mRegList); + } + mRegFile.recycleSeveral(mRegList); + mCount = count; + } + } + ~Spill() { + if (mRegList) { + if (mCount == 1) { + int reg = 31 - __builtin_clz(mRegList); + mGen.LDR(mGen.AL, reg, mGen.SP, mGen.immed12_post(4)); + } else { + mGen.LDM(mGen.AL, mGen.IA, mGen.SP, 1, mRegList); + } + mRegFile.reserveSeveral(mRegList); + } + } + private: + RegisterFile& mRegFile; + ARMAssemblerInterface& mGen; + uint32_t mRegList; + int mCount; + }; + +private: + RegisterFile mRegs; +}; + +// ---------------------------------------------------------------------------- + +class GGLAssembler : public ARMAssemblerProxy, public RegisterAllocator +{ +public: + + GGLAssembler(ARMAssemblerInterface* target); + virtual ~GGLAssembler(); + + uint32_t* base() const { return 0; } // XXX + uint32_t* pc() const { return 0; } // XXX + + void reset(int opt_level); + + virtual void prolog(); + virtual void epilog(uint32_t touched); + + // generate scanline code for given needs + int scanline(const needs_t& needs, context_t const* c); + int scanline_core(const needs_t& needs, context_t const* c); + + enum { + CLEAR_LO = 0x0001, + CLEAR_HI = 0x0002, + CORRUPTIBLE = 0x0004, + FIRST = 0x0008 + }; + + enum { //load/store flags + WRITE_BACK = 0x0001 + }; + + struct reg_t { + reg_t() : reg(-1), flags(0) { + } + reg_t(int r, int f=0) + : reg(r), flags(f) { + } + void setTo(int r, int f=0) { + reg=r; flags=f; + } + int reg; + uint16_t flags; + }; + + struct integer_t : public reg_t { + integer_t() : reg_t(), s(0) { + } + integer_t(int r, int sz=32, int f=0) + : reg_t(r, f), s(sz) { + } + void setTo(int r, int sz=32, int f=0) { + reg_t::setTo(r, f); s=sz; + } + int8_t s; + inline int size() const { return s; } + }; + + struct pixel_t : public reg_t { + pixel_t() : reg_t() { + memset(&format, 0, sizeof(GGLFormat)); + } + pixel_t(int r, const GGLFormat* fmt, int f=0) + : reg_t(r, f), format(*fmt) { + } + void setTo(int r, const GGLFormat* fmt, int f=0) { + reg_t::setTo(r, f); format = *fmt; + } + GGLFormat format; + inline int hi(int c) const { return format.c[c].h; } + inline int low(int c) const { return format.c[c].l; } + inline int mask(int c) const { return ((1<<size(c))-1) << low(c); } + inline int size() const { return format.size*8; } + inline int size(int c) const { return component_size(c); } + inline int component_size(int c) const { return hi(c) - low(c); } + }; + + struct component_t : public reg_t { + component_t() : reg_t(), h(0), l(0) { + } + component_t(int r, int f=0) + : reg_t(r, f), h(0), l(0) { + } + component_t(int r, int lo, int hi, int f=0) + : reg_t(r, f), h(hi), l(lo) { + } + explicit component_t(const integer_t& rhs) + : reg_t(rhs.reg, rhs.flags), h(rhs.s), l(0) { + } + explicit component_t(const pixel_t& rhs, int component) { + setTo( rhs.reg, + rhs.format.c[component].l, + rhs.format.c[component].h, + rhs.flags|CLEAR_LO|CLEAR_HI); + } + void setTo(int r, int lo=0, int hi=0, int f=0) { + reg_t::setTo(r, f); h=hi; l=lo; + } + int8_t h; + int8_t l; + inline int size() const { return h-l; } + }; + + struct pointer_t : public reg_t { + pointer_t() : reg_t(), size(0) { + } + pointer_t(int r, int s, int f=0) + : reg_t(r, f), size(s) { + } + void setTo(int r, int s, int f=0) { + reg_t::setTo(r, f); size=s; + } + int8_t size; + }; + + +private: + struct tex_coord_t { + reg_t s; + reg_t t; + pointer_t ptr; + }; + + struct fragment_parts_t { + uint32_t packed : 1; + uint32_t reload : 2; + uint32_t iterated_packed : 1; + pixel_t iterated; + pointer_t cbPtr; + pointer_t covPtr; + reg_t count; + reg_t argb[4]; + reg_t argb_dx[4]; + reg_t z; + reg_t dither; + pixel_t texel[GGL_TEXTURE_UNIT_COUNT]; + tex_coord_t coords[GGL_TEXTURE_UNIT_COUNT]; + }; + + struct texture_unit_t { + int format_idx; + GGLFormat format; + int bits; + int swrap; + int twrap; + int env; + int pot; + int linear; + uint8_t mask; + uint8_t replaced; + }; + + struct texture_machine_t { + texture_unit_t tmu[GGL_TEXTURE_UNIT_COUNT]; + uint8_t mask; + uint8_t replaced; + uint8_t directTexture; + uint8_t activeUnits; + }; + + struct component_info_t { + bool masked : 1; + bool inDest : 1; + bool needed : 1; + bool replaced : 1; + bool iterated : 1; + bool smooth : 1; + bool blend : 1; + bool fog : 1; + }; + + struct builder_context_t { + context_t const* c; + needs_t needs; + int Rctx; + }; + + template <typename T> + void modify(T& r, Scratch& regs) + { + if (!(r.flags & CORRUPTIBLE)) { + r.reg = regs.obtain(); + r.flags |= CORRUPTIBLE; + } + } + + // helpers + void base_offset(const pointer_t& d, const pointer_t& b, const reg_t& o); + + // texture environement + void modulate( component_t& dest, + const component_t& incoming, + const pixel_t& texel, int component); + + void decal( component_t& dest, + const component_t& incoming, + const pixel_t& texel, int component); + + void blend( component_t& dest, + const component_t& incoming, + const pixel_t& texel, int component, int tmu); + + void add( component_t& dest, + const component_t& incoming, + const pixel_t& texel, int component); + + // load/store stuff + void store(const pointer_t& addr, const pixel_t& src, uint32_t flags=0); + void load(const pointer_t& addr, const pixel_t& dest, uint32_t flags=0); + void extract(integer_t& d, const pixel_t& s, int component); + void extract(component_t& d, const pixel_t& s, int component); + void extract(integer_t& d, int s, int h, int l, int bits=32); + void expand(integer_t& d, const integer_t& s, int dbits); + void expand(integer_t& d, const component_t& s, int dbits); + void expand(component_t& d, const component_t& s, int dbits); + void downshift(pixel_t& d, int component, component_t s, const reg_t& dither); + + + void mul_factor( component_t& d, + const integer_t& v, + const integer_t& f); + + void mul_factor_add( component_t& d, + const integer_t& v, + const integer_t& f, + const component_t& a); + + void component_add( component_t& d, + const integer_t& dst, + const integer_t& src); + + void component_sat( const component_t& v); + + + void build_scanline_prolog( fragment_parts_t& parts, + const needs_t& needs); + + void build_smooth_shade(const fragment_parts_t& parts); + + void build_component( pixel_t& pixel, + const fragment_parts_t& parts, + int component, + Scratch& global_scratches); + + void build_incoming_component( + component_t& temp, + int dst_size, + const fragment_parts_t& parts, + int component, + Scratch& scratches, + Scratch& global_scratches); + + void init_iterated_color(fragment_parts_t& parts, const reg_t& x); + + void build_iterated_color( component_t& fragment, + const fragment_parts_t& parts, + int component, + Scratch& regs); + + void decodeLogicOpNeeds(const needs_t& needs); + + void decodeTMUNeeds(const needs_t& needs, context_t const* c); + + void init_textures( tex_coord_t* coords, + const reg_t& x, + const reg_t& y); + + void build_textures( fragment_parts_t& parts, + Scratch& regs); + + void filter8( const fragment_parts_t& parts, + pixel_t& texel, const texture_unit_t& tmu, + int U, int V, pointer_t& txPtr, + int FRAC_BITS); + + void filter16( const fragment_parts_t& parts, + pixel_t& texel, const texture_unit_t& tmu, + int U, int V, pointer_t& txPtr, + int FRAC_BITS); + + void filter24( const fragment_parts_t& parts, + pixel_t& texel, const texture_unit_t& tmu, + int U, int V, pointer_t& txPtr, + int FRAC_BITS); + + void filter32( const fragment_parts_t& parts, + pixel_t& texel, const texture_unit_t& tmu, + int U, int V, pointer_t& txPtr, + int FRAC_BITS); + + void build_texture_environment( component_t& fragment, + const fragment_parts_t& parts, + int component, + Scratch& regs); + + void wrapping( int d, + int coord, int size, + int tx_wrap, int tx_linear); + + void build_fog( component_t& temp, + int component, + Scratch& parent_scratches); + + void build_blending( component_t& in_out, + const pixel_t& pixel, + int component, + Scratch& parent_scratches); + + void build_blend_factor( + integer_t& factor, int f, int component, + const pixel_t& dst_pixel, + integer_t& fragment, + integer_t& fb, + Scratch& scratches); + + void build_blendFOneMinusF( component_t& temp, + const integer_t& factor, + const integer_t& fragment, + const integer_t& fb); + + void build_blendOneMinusFF( component_t& temp, + const integer_t& factor, + const integer_t& fragment, + const integer_t& fb); + + void build_coverage_application(component_t& fragment, + const fragment_parts_t& parts, + Scratch& regs); + + void build_alpha_test(component_t& fragment, const fragment_parts_t& parts); + + enum { Z_TEST=1, Z_WRITE=2 }; + void build_depth_test(const fragment_parts_t& parts, uint32_t mask); + void build_iterate_z(const fragment_parts_t& parts); + void build_iterate_f(const fragment_parts_t& parts); + void build_iterate_texture_coordinates(const fragment_parts_t& parts); + + void build_logic_op(pixel_t& pixel, Scratch& regs); + + void build_masking(pixel_t& pixel, Scratch& regs); + + void build_and_immediate(int d, int s, uint32_t mask, int bits); + + bool isAlphaSourceNeeded() const; + + enum { + FACTOR_SRC=1, FACTOR_DST=2, BLEND_SRC=4, BLEND_DST=8 + }; + + enum { + LOGIC_OP=1, LOGIC_OP_SRC=2, LOGIC_OP_DST=4 + }; + + static int blending_codes(int fs, int fd); + + builder_context_t mBuilderContext; + texture_machine_t mTextureMachine; + component_info_t mInfo[4]; + int mBlending; + int mMasking; + int mAllMasked; + int mLogicOp; + int mAlphaTest; + int mAA; + int mDithering; + int mDepthTest; + + int mSmooth; + int mFog; + pixel_t mDstPixel; + + GGLFormat mCbFormat; + + int mBlendFactorCached; + integer_t mAlphaSource; + + int mBaseRegister; + + int mBlendSrc; + int mBlendDst; + int mBlendSrcA; + int mBlendDstA; + + int mOptLevel; +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_GGLASSEMBLER_H |