1/* libs/pixelflinger/codeflinger/GGLAssembler.h
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#ifndef ANDROID_GGLASSEMBLER_H
20#define ANDROID_GGLASSEMBLER_H
21
22#include <stdint.h>
23#include <sys/types.h>
24
25#include <private/pixelflinger/ggl_context.h>
26
27#include "codeflinger/ARMAssemblerProxy.h"
28
29
30namespace android {
31
32// ----------------------------------------------------------------------------
33
34#define CONTEXT_LOAD(REG, FIELD) \
35    LDR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD)))
36
37#define CONTEXT_STORE(REG, FIELD) \
38    STR(AL, REG, mBuilderContext.Rctx, immed12_pre(GGL_OFFSETOF(FIELD)))
39
40
41class RegisterAllocator
42{
43public:
44    class RegisterFile;
45
46                    RegisterAllocator(int arch);
47    RegisterFile&   registerFile();
48    int             reserveReg(int reg);
49    int             obtainReg();
50    void            recycleReg(int reg);
51    void            reset();
52
53    class RegisterFile
54    {
55    public:
56                            RegisterFile(int arch);
57                            RegisterFile(const RegisterFile& rhs, int arch);
58                            ~RegisterFile();
59
60                void        reset();
61
62                bool operator == (const RegisterFile& rhs) const;
63                bool operator != (const RegisterFile& rhs) const {
64                    return !operator == (rhs);
65                }
66
67                int         reserve(int reg);
68                void        reserveSeveral(uint32_t regMask);
69
70                void        recycle(int reg);
71                void        recycleSeveral(uint32_t regMask);
72
73                int         obtain();
74        inline  int         isUsed(int reg) const;
75
76                bool        hasFreeRegs() const;
77                int         countFreeRegs() const;
78
79                uint32_t    touched() const;
80        inline  uint32_t    status() const { return mStatus; }
81
82        enum {
83            OUT_OF_REGISTERS = 0x1
84        };
85
86    private:
87        uint32_t    mRegs;
88        uint32_t    mTouched;
89        uint32_t    mStatus;
90        int         mArch;
91        uint32_t    mRegisterOffset;    // lets reg alloc use 2..17 for mips
92                                        // while arm uses 0..15
93    };
94
95    class Scratch
96    {
97    public:
98            Scratch(RegisterFile& regFile)
99                : mRegFile(regFile), mScratch(0) {
100            }
101            ~Scratch() {
102                mRegFile.recycleSeveral(mScratch);
103            }
104        int obtain() {
105            int reg = mRegFile.obtain();
106            mScratch |= 1<<reg;
107            return reg;
108        }
109        void recycle(int reg) {
110            mRegFile.recycle(reg);
111            mScratch &= ~(1<<reg);
112        }
113        bool isUsed(int reg) {
114            return (mScratch & (1<<reg));
115        }
116        int countFreeRegs() {
117            return mRegFile.countFreeRegs();
118        }
119    private:
120        RegisterFile&   mRegFile;
121        uint32_t        mScratch;
122    };
123
124    class Spill
125    {
126    public:
127        Spill(RegisterFile& regFile, ARMAssemblerInterface& gen, uint32_t reglist)
128            : mRegFile(regFile), mGen(gen), mRegList(reglist), mCount(0)
129        {
130            if (reglist) {
131                int count = 0;
132                while (reglist) {
133                    count++;
134                    reglist &= ~(1 << (31 - __builtin_clz(reglist)));
135                }
136                if (count == 1) {
137                    int reg = 31 - __builtin_clz(mRegList);
138                    mGen.STR(mGen.AL, reg, mGen.SP, mGen.immed12_pre(-4, 1));
139                } else {
140                    mGen.STM(mGen.AL, mGen.DB, mGen.SP, 1, mRegList);
141                }
142                mRegFile.recycleSeveral(mRegList);
143                mCount = count;
144            }
145        }
146        ~Spill() {
147            if (mRegList) {
148                if (mCount == 1) {
149                    int reg = 31 - __builtin_clz(mRegList);
150                    mGen.LDR(mGen.AL, reg, mGen.SP, mGen.immed12_post(4));
151                } else {
152                    mGen.LDM(mGen.AL, mGen.IA, mGen.SP, 1, mRegList);
153                }
154                mRegFile.reserveSeveral(mRegList);
155            }
156        }
157    private:
158        RegisterFile&           mRegFile;
159        ARMAssemblerInterface&  mGen;
160        uint32_t                mRegList;
161        int                     mCount;
162    };
163
164private:
165    RegisterFile    mRegs;
166};
167
168// ----------------------------------------------------------------------------
169
170class GGLAssembler : public ARMAssemblerProxy, public RegisterAllocator
171{
172public:
173
174                    GGLAssembler(ARMAssemblerInterface* target);
175        virtual     ~GGLAssembler();
176
177    uint32_t*   base() const { return 0; } // XXX
178    uint32_t*   pc() const { return 0; } // XXX
179
180    void        reset(int opt_level);
181
182    virtual void    prolog();
183    virtual void    epilog(uint32_t touched);
184
185        // generate scanline code for given needs
186    int         scanline(const needs_t& needs, context_t const* c);
187    int         scanline_core(const needs_t& needs, context_t const* c);
188
189        enum {
190            CLEAR_LO    = 0x0001,
191            CLEAR_HI    = 0x0002,
192            CORRUPTIBLE = 0x0004,
193            FIRST       = 0x0008
194        };
195
196        enum { //load/store flags
197            WRITE_BACK  = 0x0001
198        };
199
200        struct reg_t {
201            reg_t() : reg(-1), flags(0) {
202            }
203            reg_t(int r, int f=0)
204                : reg(r), flags(f) {
205            }
206            void setTo(int r, int f=0) {
207                reg=r; flags=f;
208            }
209            int         reg;
210            uint16_t    flags;
211        };
212
213        struct integer_t : public reg_t {
214            integer_t() : reg_t(), s(0) {
215            }
216            integer_t(int r, int sz=32, int f=0)
217                : reg_t(r, f), s(sz) {
218            }
219            void setTo(int r, int sz=32, int f=0) {
220                reg_t::setTo(r, f); s=sz;
221            }
222            int8_t s;
223            inline int size() const { return s; }
224        };
225
226        struct pixel_t : public reg_t {
227            pixel_t() : reg_t() {
228                memset(&format, 0, sizeof(GGLFormat));
229            }
230            pixel_t(int r, const GGLFormat* fmt, int f=0)
231                : reg_t(r, f), format(*fmt) {
232            }
233            void setTo(int r, const GGLFormat* fmt, int f=0) {
234                reg_t::setTo(r, f); format = *fmt;
235            }
236            GGLFormat format;
237            inline int hi(int c) const { return format.c[c].h; }
238            inline int low(int c) const { return format.c[c].l; }
239            inline int mask(int c) const { return ((1<<size(c))-1) << low(c); }
240            inline int size() const { return format.size*8; }
241            inline int size(int c) const { return component_size(c); }
242            inline int component_size(int c) const { return hi(c) - low(c); }
243        };
244
245        struct component_t : public reg_t {
246            component_t() : reg_t(), h(0), l(0) {
247            }
248            component_t(int r, int f=0)
249                : reg_t(r, f), h(0), l(0) {
250            }
251            component_t(int r, int lo, int hi, int f=0)
252                : reg_t(r, f), h(hi), l(lo) {
253            }
254            explicit component_t(const integer_t& rhs)
255                : reg_t(rhs.reg, rhs.flags), h(rhs.s), l(0) {
256            }
257            explicit component_t(const pixel_t& rhs, int component) {
258                setTo(  rhs.reg,
259                        rhs.format.c[component].l,
260                        rhs.format.c[component].h,
261                        rhs.flags|CLEAR_LO|CLEAR_HI);
262            }
263            void setTo(int r, int lo=0, int hi=0, int f=0) {
264                reg_t::setTo(r, f); h=hi; l=lo;
265            }
266            int8_t h;
267            int8_t l;
268            inline int size() const { return h-l; }
269        };
270
271        struct pointer_t : public reg_t {
272            pointer_t() : reg_t(), size(0) {
273            }
274            pointer_t(int r, int s, int f=0)
275                : reg_t(r, f), size(s) {
276            }
277            void setTo(int r, int s, int f=0) {
278                reg_t::setTo(r, f); size=s;
279            }
280            int8_t size;
281        };
282
283
284private:
285    struct tex_coord_t {
286        reg_t       s;
287        reg_t       t;
288        pointer_t   ptr;
289    };
290
291    struct fragment_parts_t {
292        uint32_t    packed  : 1;
293        uint32_t    reload  : 2;
294        uint32_t    iterated_packed  : 1;
295        pixel_t     iterated;
296        pointer_t   cbPtr;
297        pointer_t   covPtr;
298        reg_t       count;
299        reg_t       argb[4];
300        reg_t       argb_dx[4];
301        reg_t       z;
302        reg_t       dither;
303        pixel_t     texel[GGL_TEXTURE_UNIT_COUNT];
304        tex_coord_t coords[GGL_TEXTURE_UNIT_COUNT];
305    };
306
307    struct texture_unit_t {
308        int         format_idx;
309        GGLFormat   format;
310        int         bits;
311        int         swrap;
312        int         twrap;
313        int         env;
314        int         pot;
315        int         linear;
316        uint8_t     mask;
317        uint8_t     replaced;
318    };
319
320    struct texture_machine_t {
321        texture_unit_t  tmu[GGL_TEXTURE_UNIT_COUNT];
322        uint8_t         mask;
323        uint8_t         replaced;
324        uint8_t         directTexture;
325        uint8_t         activeUnits;
326    };
327
328    struct component_info_t {
329        bool    masked      : 1;
330        bool    inDest      : 1;
331        bool    needed      : 1;
332        bool    replaced    : 1;
333        bool    iterated    : 1;
334        bool    smooth      : 1;
335        bool    blend       : 1;
336        bool    fog         : 1;
337    };
338
339    struct builder_context_t {
340        context_t const*    c;
341        needs_t             needs;
342        int                 Rctx;
343    };
344
345    template <typename T>
346    void modify(T& r, Scratch& regs)
347    {
348        if (!(r.flags & CORRUPTIBLE)) {
349            r.reg = regs.obtain();
350            r.flags |= CORRUPTIBLE;
351        }
352    }
353
354    // helpers
355    void    base_offset(const pointer_t& d, const pointer_t& b, const reg_t& o);
356
357    // texture environement
358    void    modulate(   component_t& dest,
359                        const component_t& incoming,
360                        const pixel_t& texel, int component);
361
362    void    decal(  component_t& dest,
363                    const component_t& incoming,
364                    const pixel_t& texel, int component);
365
366    void    blend(  component_t& dest,
367                    const component_t& incoming,
368                    const pixel_t& texel, int component, int tmu);
369
370    void    add(  component_t& dest,
371                    const component_t& incoming,
372                    const pixel_t& texel, int component);
373
374    // load/store stuff
375    void    store(const pointer_t& addr, const pixel_t& src, uint32_t flags=0);
376    void    load(const pointer_t& addr, const pixel_t& dest, uint32_t flags=0);
377    void    extract(integer_t& d, const pixel_t& s, int component);
378    void    extract(component_t& d, const pixel_t& s, int component);
379    void    extract(integer_t& d, int s, int h, int l, int bits=32);
380    void    expand(integer_t& d, const integer_t& s, int dbits);
381    void    expand(integer_t& d, const component_t& s, int dbits);
382    void    expand(component_t& d, const component_t& s, int dbits);
383    void    downshift(pixel_t& d, int component, component_t s, const reg_t& dither);
384
385
386    void    mul_factor( component_t& d,
387                        const integer_t& v,
388                        const integer_t& f);
389
390    void    mul_factor_add( component_t& d,
391                            const integer_t& v,
392                            const integer_t& f,
393                            const component_t& a);
394
395    void    component_add(  component_t& d,
396                            const integer_t& dst,
397                            const integer_t& src);
398
399    void    component_sat(  const component_t& v);
400
401
402    void    build_scanline_prolog(  fragment_parts_t& parts,
403                                    const needs_t& needs);
404
405    void    build_smooth_shade(const fragment_parts_t& parts);
406
407    void    build_component(    pixel_t& pixel,
408                                const fragment_parts_t& parts,
409                                int component,
410                                Scratch& global_scratches);
411
412    void    build_incoming_component(
413                                component_t& temp,
414                                int dst_size,
415                                const fragment_parts_t& parts,
416                                int component,
417                                Scratch& scratches,
418                                Scratch& global_scratches);
419
420    void    init_iterated_color(fragment_parts_t& parts, const reg_t& x);
421
422    void    build_iterated_color(   component_t& fragment,
423                                    const fragment_parts_t& parts,
424                                    int component,
425                                    Scratch& regs);
426
427    void    decodeLogicOpNeeds(const needs_t& needs);
428
429    void    decodeTMUNeeds(const needs_t& needs, context_t const* c);
430
431    void    init_textures(  tex_coord_t* coords,
432                            const reg_t& x,
433                            const reg_t& y);
434
435    void    build_textures( fragment_parts_t& parts,
436                            Scratch& regs);
437
438    void    filter8(   const fragment_parts_t& parts,
439                        pixel_t& texel, const texture_unit_t& tmu,
440                        int U, int V, pointer_t& txPtr,
441                        int FRAC_BITS);
442
443    void    filter16(   const fragment_parts_t& parts,
444                        pixel_t& texel, const texture_unit_t& tmu,
445                        int U, int V, pointer_t& txPtr,
446                        int FRAC_BITS);
447
448    void    filter24(   const fragment_parts_t& parts,
449                        pixel_t& texel, const texture_unit_t& tmu,
450                        int U, int V, pointer_t& txPtr,
451                        int FRAC_BITS);
452
453    void    filter32(   const fragment_parts_t& parts,
454                        pixel_t& texel, const texture_unit_t& tmu,
455                        int U, int V, pointer_t& txPtr,
456                        int FRAC_BITS);
457
458    void    build_texture_environment(  component_t& fragment,
459                                        const fragment_parts_t& parts,
460                                        int component,
461                                        Scratch& regs);
462
463    void    wrapping(   int d,
464                        int coord, int size,
465                        int tx_wrap, int tx_linear);
466
467    void    build_fog(  component_t& temp,
468                        int component,
469                        Scratch& parent_scratches);
470
471    void    build_blending(     component_t& in_out,
472                                const pixel_t& pixel,
473                                int component,
474                                Scratch& parent_scratches);
475
476    void    build_blend_factor(
477                integer_t& factor, int f, int component,
478                const pixel_t& dst_pixel,
479                integer_t& fragment,
480                integer_t& fb,
481                Scratch& scratches);
482
483    void    build_blendFOneMinusF(  component_t& temp,
484                                    const integer_t& factor,
485                                    const integer_t& fragment,
486                                    const integer_t& fb);
487
488    void    build_blendOneMinusFF(  component_t& temp,
489                                    const integer_t& factor,
490                                    const integer_t& fragment,
491                                    const integer_t& fb);
492
493    void build_coverage_application(component_t& fragment,
494                                    const fragment_parts_t& parts,
495                                    Scratch& regs);
496
497    void build_alpha_test(component_t& fragment, const fragment_parts_t& parts);
498
499    enum { Z_TEST=1, Z_WRITE=2 };
500    void build_depth_test(const fragment_parts_t& parts, uint32_t mask);
501    void build_iterate_z(const fragment_parts_t& parts);
502    void build_iterate_f(const fragment_parts_t& parts);
503    void build_iterate_texture_coordinates(const fragment_parts_t& parts);
504
505    void build_logic_op(pixel_t& pixel, Scratch& regs);
506
507    void build_masking(pixel_t& pixel, Scratch& regs);
508
509    void build_and_immediate(int d, int s, uint32_t mask, int bits);
510
511    bool    isAlphaSourceNeeded() const;
512
513    enum {
514        FACTOR_SRC=1, FACTOR_DST=2, BLEND_SRC=4, BLEND_DST=8
515    };
516
517    enum {
518        LOGIC_OP=1, LOGIC_OP_SRC=2, LOGIC_OP_DST=4
519    };
520
521    static int blending_codes(int fs, int fd);
522
523    builder_context_t   mBuilderContext;
524    texture_machine_t   mTextureMachine;
525    component_info_t    mInfo[4];
526    int                 mBlending;
527    int                 mMasking;
528    int                 mAllMasked;
529    int                 mLogicOp;
530    int                 mAlphaTest;
531    int                 mAA;
532    int                 mDithering;
533    int                 mDepthTest;
534
535    int             mSmooth;
536    int             mFog;
537    pixel_t         mDstPixel;
538
539    GGLFormat       mCbFormat;
540
541    int             mBlendFactorCached;
542    integer_t       mAlphaSource;
543
544    int             mBaseRegister;
545
546    int             mBlendSrc;
547    int             mBlendDst;
548    int             mBlendSrcA;
549    int             mBlendDstA;
550
551    int             mOptLevel;
552};
553
554// ----------------------------------------------------------------------------
555
556}; // namespace android
557
558#endif // ANDROID_GGLASSEMBLER_H
559