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