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