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