summaryrefslogtreecommitdiffstats
path: root/libpixelflinger/codeflinger/GGLAssembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'libpixelflinger/codeflinger/GGLAssembler.h')
-rw-r--r--libpixelflinger/codeflinger/GGLAssembler.h554
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