1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_OPENGLES_CONTEXT_H
18#define ANDROID_OPENGLES_CONTEXT_H
19
20#include <stdint.h>
21#include <stddef.h>
22#include <sys/types.h>
23#include <pthread.h>
24#ifdef __ANDROID__
25#include <bionic_tls.h>
26#endif
27
28#include <private/pixelflinger/ggl_context.h>
29
30#include <system/window.h>
31
32#include <GLES/gl.h>
33#include <GLES/glext.h>
34
35namespace android {
36
37
38const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10
39#ifdef GL_OES_compressed_ETC1_RGB8_texture
40        + 1
41#endif
42        ;
43
44class EGLTextureObject;
45class EGLSurfaceManager;
46class EGLBufferObjectManager;
47
48namespace gl {
49
50struct ogles_context_t;
51struct matrixx_t;
52struct transform_t;
53struct buffer_t;
54
55ogles_context_t* getGlContext();
56
57template<typename T>
58static inline void swap(T& a, T& b) {
59    T t(a); a = b; b = t;
60}
61template<typename T>
62inline T max(T a, T b) {
63    return a<b ? b : a;
64}
65template<typename T>
66inline T max(T a, T b, T c) {
67    return max(a, max(b, c));
68}
69template<typename T>
70inline T min(T a, T b) {
71    return a<b ? a : b;
72}
73template<typename T>
74inline T min(T a, T b, T c) {
75    return min(a, min(b, c));
76}
77template<typename T>
78inline T min(T a, T b, T c, T d) {
79    return min(min(a,b), min(c,d));
80}
81
82// ----------------------------------------------------------------------------
83// vertices
84// ----------------------------------------------------------------------------
85
86struct vec3_t {
87    union {
88        struct { GLfixed x, y, z; };
89        struct { GLfixed r, g, b; };
90        struct { GLfixed S, T, R; };
91        GLfixed v[3];
92    };
93};
94
95struct vec4_t {
96    union {
97        struct { GLfixed x, y, z, w; };
98        struct { GLfixed r, g, b, a; };
99        struct { GLfixed S, T, R, Q; };
100        GLfixed v[4];
101    };
102};
103
104struct vertex_t {
105    enum {
106        // these constant matter for our clipping
107        CLIP_L          = 0x0001,   // clipping flags
108        CLIP_R          = 0x0002,
109        CLIP_B          = 0x0004,
110        CLIP_T          = 0x0008,
111        CLIP_N          = 0x0010,
112        CLIP_F          = 0x0020,
113
114        EYE             = 0x0040,
115        RESERVED        = 0x0080,
116
117        USER_CLIP_0     = 0x0100,   // user clipping flags
118        USER_CLIP_1     = 0x0200,
119        USER_CLIP_2     = 0x0400,
120        USER_CLIP_3     = 0x0800,
121        USER_CLIP_4     = 0x1000,
122        USER_CLIP_5     = 0x2000,
123
124        LIT             = 0x4000,   // lighting has been applied
125        TT              = 0x8000,   // texture coords transformed
126
127        FRUSTUM_CLIP_ALL= 0x003F,
128        USER_CLIP_ALL   = 0x3F00,
129        CLIP_ALL        = 0x3F3F,
130    };
131
132    // the fields below are arranged to minimize d-cache usage
133    // we group together, by cache-line, the fields most likely to be used
134
135    union {
136    vec4_t          obj;
137    vec4_t          eye;
138    };
139    vec4_t          clip;
140
141    uint32_t        flags;
142    size_t          index;  // cache tag, and vertex index
143    GLfixed         fog;
144    uint8_t         locked;
145    uint8_t         mru;
146    uint8_t         reserved[2];
147    vec4_t          window;
148
149    vec4_t          color;
150    vec4_t          texture[GGL_TEXTURE_UNIT_COUNT];
151#ifdef __LP64__
152    uint32_t        reserved1[2];
153#else
154    uint32_t        reserved1[4];
155#endif
156
157    inline void clear() {
158        flags = index = locked = mru = 0;
159    }
160};
161
162struct point_size_t {
163    GGLcoord    size;
164    GLboolean   smooth;
165};
166
167struct line_width_t {
168    GGLcoord    width;
169    GLboolean   smooth;
170};
171
172struct polygon_offset_t {
173    GLfixed     factor;
174    GLfixed     units;
175    GLboolean   enable;
176};
177
178// ----------------------------------------------------------------------------
179// arrays
180// ----------------------------------------------------------------------------
181
182struct array_t {
183    typedef void (*fetcher_t)(ogles_context_t*, GLfixed*, const GLvoid*);
184    fetcher_t       fetch;
185    GLvoid const*   physical_pointer;
186    GLint           size;
187    GLsizei         stride;
188    GLvoid const*   pointer;
189    buffer_t const* bo;
190    uint16_t        type;
191    GLboolean       enable;
192    GLboolean       pad;
193    GLsizei         bounds;
194    void init(GLint, GLenum, GLsizei, const GLvoid *, const buffer_t*, GLsizei);
195    inline void resolve();
196    inline const GLubyte* element(GLint i) const {
197        return (const GLubyte*)physical_pointer + i * stride;
198    }
199};
200
201struct array_machine_t {
202    array_t         vertex;
203    array_t         normal;
204    array_t         color;
205    array_t         texture[GGL_TEXTURE_UNIT_COUNT];
206    uint8_t         activeTexture;
207    uint8_t         tmu;
208    uint16_t        cull;
209    uint32_t        flags;
210    GLenum          indicesType;
211    buffer_t const* array_buffer;
212    buffer_t const* element_array_buffer;
213
214    void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei);
215    void (*compileElement)(ogles_context_t*, vertex_t*, GLint);
216
217    void (*mvp_transform)(transform_t const*, vec4_t*, vec4_t const*);
218    void (*mv_transform)(transform_t const*, vec4_t*, vec4_t const*);
219    void (*tex_transform[2])(transform_t const*, vec4_t*, vec4_t const*);
220    void (*perspective)(ogles_context_t*c, vertex_t* v);
221    void (*clipVertex)(ogles_context_t* c, vertex_t* nv,
222            GGLfixed t, const vertex_t* s, const vertex_t* p);
223    void (*clipEye)(ogles_context_t* c, vertex_t* nv,
224            GGLfixed t, const vertex_t* s, const vertex_t* p);
225};
226
227struct vertex_cache_t {
228    enum {
229        // must be at least 4
230        // 3 vertice for triangles
231        // or 2 + 2 for indexed triangles w/ cache contention
232        VERTEX_BUFFER_SIZE  = 8,
233        // must be a power of two and at least 3
234        VERTEX_CACHE_SIZE   = 64,   // 8 KB
235
236        INDEX_BITS      = 16,
237        INDEX_MASK      = ((1LU<<INDEX_BITS)-1),
238        INDEX_SEQ       = 1LU<<INDEX_BITS,
239    };
240    vertex_t*       vBuffer;
241    vertex_t*       vCache;
242    uint32_t        sequence;
243    void*           base;
244    uint32_t        total;
245    uint32_t        misses;
246    int64_t         startTime;
247    void init();
248    void uninit();
249    void clear();
250    void dump_stats(GLenum mode);
251};
252
253// ----------------------------------------------------------------------------
254// fog
255// ----------------------------------------------------------------------------
256
257struct fog_t {
258    GLfixed     density;
259    GLfixed     start;
260    GLfixed     end;
261    GLfixed     invEndMinusStart;
262    GLenum      mode;
263    GLfixed     (*fog)(ogles_context_t* c, GLfixed z);
264};
265
266// ----------------------------------------------------------------------------
267// user clip planes
268// ----------------------------------------------------------------------------
269
270const unsigned int OGLES_MAX_CLIP_PLANES = 6;
271
272struct clip_plane_t {
273    vec4_t      equation;
274};
275
276struct user_clip_planes_t {
277    clip_plane_t    plane[OGLES_MAX_CLIP_PLANES];
278    uint32_t        enable;
279};
280
281// ----------------------------------------------------------------------------
282// lighting
283// ----------------------------------------------------------------------------
284
285const unsigned int OGLES_MAX_LIGHTS = 8;
286
287struct light_t {
288    vec4_t      ambient;
289    vec4_t      diffuse;
290    vec4_t      specular;
291    vec4_t      implicitAmbient;
292    vec4_t      implicitDiffuse;
293    vec4_t      implicitSpecular;
294    vec4_t      position;       // position in eye space
295    vec4_t      objPosition;
296    vec4_t      normalizedObjPosition;
297    vec4_t      spotDir;
298    vec4_t      normalizedSpotDir;
299    GLfixed     spotExp;
300    GLfixed     spotCutoff;
301    GLfixed     spotCutoffCosine;
302    GLfixed     attenuation[3];
303    GLfixed     rConstAttenuation;
304    GLboolean   enable;
305};
306
307struct material_t {
308    vec4_t      ambient;
309    vec4_t      diffuse;
310    vec4_t      specular;
311    vec4_t      emission;
312    GLfixed     shininess;
313};
314
315struct light_model_t {
316    vec4_t      ambient;
317    GLboolean   twoSide;
318};
319
320struct color_material_t {
321    GLenum      face;
322    GLenum      mode;
323    GLboolean   enable;
324};
325
326struct lighting_t {
327    light_t             lights[OGLES_MAX_LIGHTS];
328    material_t          front;
329    light_model_t       lightModel;
330    color_material_t    colorMaterial;
331    vec4_t              implicitSceneEmissionAndAmbient;
332    vec4_t              objViewer;
333    uint32_t            enabledLights;
334    GLboolean           enable;
335    GLenum              shadeModel;
336    typedef void (*light_fct_t)(ogles_context_t*, vertex_t*);
337    void (*lightVertex)(ogles_context_t* c, vertex_t* v);
338    void (*lightTriangle)(ogles_context_t* c,
339            vertex_t* v0, vertex_t* v1, vertex_t* v2);
340};
341
342struct culling_t {
343    GLenum      cullFace;
344    GLenum      frontFace;
345    GLboolean   enable;
346};
347
348// ----------------------------------------------------------------------------
349// textures
350// ----------------------------------------------------------------------------
351
352struct texture_unit_t {
353    GLuint              name;
354    EGLTextureObject*   texture;
355    uint8_t             dirty;
356};
357
358struct texture_state_t
359{
360    texture_unit_t      tmu[GGL_TEXTURE_UNIT_COUNT];
361    int                 active;     // active tmu
362    EGLTextureObject*   defaultTexture;
363    GGLContext*         ggl;
364    uint8_t             packAlignment;
365    uint8_t             unpackAlignment;
366};
367
368// ----------------------------------------------------------------------------
369// transformation and matrices
370// ----------------------------------------------------------------------------
371
372struct matrixf_t;
373
374struct matrixx_t {
375    GLfixed m[16];
376    void load(const matrixf_t& rhs);
377};
378
379struct matrix_stack_t;
380
381
382struct matrixf_t {
383    void loadIdentity();
384    void load(const matrixf_t& rhs);
385
386    inline GLfloat* editElements() { return m; }
387    inline GLfloat const* elements() const { return m; }
388
389    void set(const GLfixed* rhs);
390    void set(const GLfloat* rhs);
391
392    static void multiply(matrixf_t& r,
393            const matrixf_t& lhs, const matrixf_t& rhs);
394
395    void dump(const char* what);
396
397private:
398    friend struct matrix_stack_t;
399    GLfloat     m[16];
400    void load(const GLfixed* rhs);
401    void load(const GLfloat* rhs);
402    void multiply(const matrixf_t& rhs);
403    void translate(GLfloat x, GLfloat y, GLfloat z);
404    void scale(GLfloat x, GLfloat y, GLfloat z);
405    void rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z);
406};
407
408enum {
409    OP_IDENTITY         = 0x00,
410    OP_TRANSLATE        = 0x01,
411    OP_UNIFORM_SCALE    = 0x02,
412    OP_SCALE            = 0x05,
413    OP_ROTATE           = 0x08,
414    OP_SKEW             = 0x10,
415    OP_ALL              = 0x1F
416};
417
418struct transform_t {
419    enum {
420        FLAGS_2D_PROJECTION = 0x1
421    };
422    matrixx_t       matrix;
423    uint32_t        flags;
424    uint32_t        ops;
425
426    union {
427        struct {
428            void (*point2)(transform_t const* t, vec4_t*, vec4_t const*);
429            void (*point3)(transform_t const* t, vec4_t*, vec4_t const*);
430            void (*point4)(transform_t const* t, vec4_t*, vec4_t const*);
431        };
432        void (*pointv[3])(transform_t const* t, vec4_t*, vec4_t const*);
433    };
434
435    void loadIdentity();
436    void picker();
437    void dump(const char* what);
438};
439
440struct mvui_transform_t : public transform_t
441{
442    void picker();
443};
444
445struct matrix_stack_t {
446    enum {
447        DO_PICKER           = 0x1,
448        DO_FLOAT_TO_FIXED   = 0x2
449    };
450    transform_t     transform;
451    uint8_t         maxDepth;
452    uint8_t         depth;
453    uint8_t         dirty;
454    uint8_t         reserved;
455    matrixf_t       *stack;
456    uint8_t         *ops;
457    void init(int depth);
458    void uninit();
459    void loadIdentity();
460    void load(const GLfixed* rhs);
461    void load(const GLfloat* rhs);
462    void multiply(const matrixf_t& rhs);
463    void translate(GLfloat x, GLfloat y, GLfloat z);
464    void scale(GLfloat x, GLfloat y, GLfloat z);
465    void rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z);
466    GLint push();
467    GLint pop();
468    void validate();
469    matrixf_t& top() { return stack[depth]; }
470    const matrixf_t& top() const { return stack[depth]; }
471    uint32_t top_ops() const { return ops[depth]; }
472    inline bool isRigidBody() const {
473        return !(ops[depth] & ~(OP_TRANSLATE|OP_UNIFORM_SCALE|OP_ROTATE));
474    }
475};
476
477struct vp_transform_t {
478    transform_t     transform;
479    matrixf_t       matrix;
480    GLfloat         zNear;
481    GLfloat         zFar;
482    void loadIdentity();
483};
484
485struct transform_state_t {
486    enum {
487        MODELVIEW           = 0x01,
488        PROJECTION          = 0x02,
489        VIEWPORT            = 0x04,
490        TEXTURE             = 0x08,
491        MVUI                = 0x10,
492        MVIT                = 0x20,
493        MVP                 = 0x40,
494    };
495    matrix_stack_t      *current;
496    matrix_stack_t      modelview;
497    matrix_stack_t      projection;
498    matrix_stack_t      texture[GGL_TEXTURE_UNIT_COUNT];
499
500    // modelview * projection
501    transform_t         mvp     __attribute__((aligned(32)));
502    // viewport transformation
503    vp_transform_t      vpt     __attribute__((aligned(32)));
504    // same for 4-D vertices
505    transform_t         mvp4;
506    // full modelview inverse transpose
507    transform_t         mvit4;
508    // upper 3x3 of mv-inverse-transpose (for normals)
509    mvui_transform_t    mvui;
510
511    GLenum              matrixMode;
512    GLenum              rescaleNormals;
513    uint32_t            dirty;
514    void invalidate();
515    void update_mvp();
516    void update_mvit();
517    void update_mvui();
518};
519
520struct viewport_t {
521    GLint       x;
522    GLint       y;
523    GLsizei     w;
524    GLsizei     h;
525    struct {
526        GLint       x;
527        GLint       y;
528    } surfaceport;
529    struct {
530        GLint       x;
531        GLint       y;
532        GLsizei     w;
533        GLsizei     h;
534    } scissor;
535};
536
537// ----------------------------------------------------------------------------
538// Lerping
539// ----------------------------------------------------------------------------
540
541struct compute_iterators_t
542{
543    void initTriangle(
544            vertex_t const* v0,
545            vertex_t const* v1,
546            vertex_t const* v2);
547
548    void initLine(
549            vertex_t const* v0,
550            vertex_t const* v1);
551
552    inline void initLerp(vertex_t const* v0, uint32_t enables);
553
554    int iteratorsScale(int32_t it[3],
555            int32_t c0, int32_t c1, int32_t c2) const;
556
557    void iterators1616(GGLfixed it[3],
558            GGLfixed c0, GGLfixed c1, GGLfixed c2) const;
559
560    void iterators0032(int32_t it[3],
561            int32_t c0, int32_t c1, int32_t c2) const;
562
563    void iterators0032(int64_t it[3],
564            int32_t c0, int32_t c1, int32_t c2) const;
565
566    GGLcoord area() const { return m_area; }
567
568private:
569    // don't change order of members here -- used by iterators.S
570    GGLcoord m_dx01, m_dy10, m_dx20, m_dy02;
571    GGLcoord m_x0, m_y0;
572    GGLcoord m_area;
573    uint8_t m_scale;
574    uint8_t m_area_scale;
575    uint8_t m_reserved[2];
576
577};
578
579// ----------------------------------------------------------------------------
580// state
581// ----------------------------------------------------------------------------
582
583#ifdef __ANDROID__
584    // We have a dedicated TLS slot in bionic
585    inline void setGlThreadSpecific(ogles_context_t *value) {
586        __get_tls()[TLS_SLOT_OPENGL] = value;
587    }
588    inline ogles_context_t* getGlThreadSpecific() {
589        return static_cast<ogles_context_t*>(__get_tls()[TLS_SLOT_OPENGL]);
590    }
591#else
592    extern pthread_key_t gGLKey;
593    inline void setGlThreadSpecific(ogles_context_t *value) {
594        pthread_setspecific(gGLKey, value);
595    }
596    inline ogles_context_t* getGlThreadSpecific() {
597        return static_cast<ogles_context_t*>(pthread_getspecific(gGLKey));
598    }
599#endif
600
601
602struct prims_t {
603    typedef ogles_context_t* GL;
604    void (*renderPoint)(GL, vertex_t*);
605    void (*renderLine)(GL, vertex_t*, vertex_t*);
606    void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
607};
608
609struct ogles_context_t {
610    context_t               rasterizer;
611    array_machine_t         arrays         __attribute__((aligned(32)));
612    texture_state_t         textures;
613    transform_state_t       transforms;
614    vertex_cache_t          vc;
615    prims_t                 prims;
616    culling_t               cull;
617    lighting_t              lighting;
618    user_clip_planes_t      clipPlanes;
619    compute_iterators_t     lerp           __attribute__((aligned(32)));
620    vertex_t                current;
621    vec4_t                  currentColorClamped;
622    vec3_t                  currentNormal;
623    viewport_t              viewport;
624    point_size_t            point;
625    line_width_t            line;
626    polygon_offset_t        polygonOffset;
627    fog_t                   fog;
628    uint32_t                perspective : 1;
629    uint32_t                transformTextures : 1;
630    EGLSurfaceManager*      surfaceManager;
631    EGLBufferObjectManager* bufferObjectManager;
632
633    GLenum                  error;
634
635    static inline ogles_context_t* get() {
636        return getGlThreadSpecific();
637    }
638
639};
640
641}; // namespace gl
642}; // namespace android
643
644using namespace android::gl;
645
646#endif // ANDROID_OPENGLES_CONTEXT_H
647
648