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