aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gl/SkGL.h
blob: 9f79ad16fc1b288557adb189d14671fff545d4ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#ifndef SkGL_DEFINED
#define SkGL_DEFINED

#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_SDL)
    #include <OpenGL/gl.h>
    #include <OpenGL/glext.h>
    #include <AGL/agl.h>
    // use FBOs for devices
    #define SK_GL_DEVICE_FBO
#elif defined(ANDROID)
    #include <GLES/gl.h>
    #include <EGL/egl.h>
    #include <GLES/glext.h>
#endif

#include "SkColor.h"
#include "SkMatrix.h"
#include "SkShader.h"

class SkPaint;
class SkPath;

class SkGLClipIter;

//#define TRACE_TEXTURE_CREATE

static void SkGL_unimpl(const char str[]) {
    SkDebugf("SkGL unimplemented: %s\n", str);
}
///////////////////////////////////////////////////////////////////////////////

#if GL_OES_compressed_paletted_texture
    #define SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D
#endif

#if GL_OES_fixed_point && defined(SK_SCALAR_IS_FIXED)
    #define SK_GLType   GL_FIXED
#else
    #define SK_GLType   GL_FLOAT
#endif

#if SK_GLType == GL_FIXED
    typedef SkFixed SkGLScalar;

    #define SkIntToGL(n)        SkIntToFixed(n)
    #define SkScalarToGL(x)     SkScalarToFixed(x)
    #define SK_GLScalar1        SK_Fixed1
    #define SkGLScalarMul(a, b) SkFixedMul(a, b)
    #define MAKE_GL(name)       name ## x

    #ifdef SK_SCALAR_IS_FIXED
        #define GLSCALAR_IS_SCALAR  1
        #define SkPerspToGL(x)      SkFractToFixed(x)
    #else
        #define GLSCALAR_IS_SCALAR  0
        #define SkPerspToGL(x)      SkFractToFloat(x)
    #endif
#else
    typedef float SkGLScalar;

    #define SkIntToGL(n)        (n)
    #define SkScalarToGL(x)     SkScalarToFloat(x)
    #define SK_GLScalar1        (1.f)
    #define SkGLScalarMul(a, b) ((a) * (b))
    #define MAKE_GL(name)       name ## f

    #ifdef SK_SCALAR_IS_FLOAT
        #define GLSCALAR_IS_SCALAR  1
        #define SkPerspToGL(x)      (x)
    #else
        #define GLSCALAR_IS_SCALAR  0
        #define SkPerspToGL(x)      SkFractToFloat(x)
    #endif
#endif

#if GL_OES_fixed_point
    typedef SkFixed SkGLTextScalar;
    #define SK_TextGLType       GL_FIXED

    #define SkIntToTextGL(n)    SkIntToFixed(n)
    #define SkFixedToTextGL(x)  (x)

    #define SK_glTexParameteri(target, pname, param) \
                glTexParameterx(target, pname, param)
#else
    typedef float SkGLTextScalar;
    #define SK_TextGLType       SK_GLType
    #define SK_GL_HAS_COLOR4UB

    #define SkIntToTextGL(n)    SkIntToGL(n)
    #define SkFixedToTextGL(x)  SkFixedToFloat(x)


    #define SK_glTexParameteri(target, pname, param) \
                glTexParameteri(target, pname, param)
#endif

///////////////////////////////////////////////////////////////////////////////

// text has its own vertex class, since it may want to be in fixed point (given)
// that it starts with all integers) even when the default vertices are floats
struct SkGLTextVertex {
    SkGLTextScalar fX;
    SkGLTextScalar fY;
    
    void setI(int x, int y) {
        fX = SkIntToTextGL(x);
        fY = SkIntToTextGL(y);
    }
    
    void setX(SkFixed x, SkFixed y) {
        fX = SkFixedToTextGL(x);
        fY = SkFixedToTextGL(y);
    }
    
    // counter-clockwise fan
    void setIRectFan(int l, int t, int r, int b) {
        SkGLTextVertex* SK_RESTRICT v = this;
        v[0].setI(l, t);
        v[1].setI(l, b);
        v[2].setI(r, b);
        v[3].setI(r, t);
    }
    
    // counter-clockwise fan
    void setXRectFan(SkFixed l, SkFixed t, SkFixed r, SkFixed b) {
        SkGLTextVertex* SK_RESTRICT v = this;
        v[0].setX(l, t);
        v[1].setX(l, b);
        v[2].setX(r, b);
        v[3].setX(r, t);
    }
};

struct SkGLVertex {
    SkGLScalar  fX;
    SkGLScalar  fY;
    
    void setGL(SkGLScalar x, SkGLScalar y) {
        fX = x;
        fY = y;
    }

    void setScalars(SkScalar x, SkScalar y) {
        fX = SkScalarToGL(x);
        fY = SkScalarToGL(y);
    }
    
    void setPoint(const SkPoint& pt) {
        fX = SkScalarToGL(pt.fX);
        fY = SkScalarToGL(pt.fY);
    }
    
    void setPoints(const SkPoint* SK_RESTRICT pts, int count) {
        const SkScalar* SK_RESTRICT src = (const SkScalar*)pts;
        SkGLScalar* SK_RESTRICT dst = (SkGLScalar*)this;
        for (int i = 0; i < count; i++) {
            *dst++ = SkScalarToGL(*src++);
            *dst++ = SkScalarToGL(*src++);
        }
    }
    
    // counter-clockwise fan
    void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
        SkGLVertex* v = this;
        v[0].setScalars(l, t);
        v[1].setScalars(l, b);
        v[2].setScalars(r, b);
        v[3].setScalars(r, t);
    }
    
    // counter-clockwise fan
    void setIRectFan(int l, int t, int r, int b) {
        SkGLVertex* v = this;
        v[0].setGL(SkIntToGL(l), SkIntToGL(t));
        v[1].setGL(SkIntToGL(l), SkIntToGL(b));
        v[2].setGL(SkIntToGL(r), SkIntToGL(b));
        v[3].setGL(SkIntToGL(r), SkIntToGL(t));
    }
    
    // counter-clockwise fan
    void setRectFan(const SkRect& r) {
        this->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom);
    }
    
    // counter-clockwise fan
    void setIRectFan(const SkIRect& r) {
        this->setIRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom);
    }
};

struct SkGLMatrix {
    SkGLScalar fMat[16];
    
    void reset() {
        sk_bzero(fMat, sizeof(fMat));
        fMat[0] = fMat[5] = fMat[10] = fMat[15] = SK_GLScalar1;
    }
    
    void set(const SkMatrix& m) {
        sk_bzero(fMat, sizeof(fMat));
        fMat[0] = SkScalarToGL(m[SkMatrix::kMScaleX]);
        fMat[4] = SkScalarToGL(m[SkMatrix::kMSkewX]);
        fMat[12] = SkScalarToGL(m[SkMatrix::kMTransX]);
        
        fMat[1] = SkScalarToGL(m[SkMatrix::kMSkewY]);
        fMat[5] = SkScalarToGL(m[SkMatrix::kMScaleY]);
        fMat[13] = SkScalarToGL(m[SkMatrix::kMTransY]);
                
        fMat[3] = SkPerspToGL(m[SkMatrix::kMPersp0]);
        fMat[7] = SkPerspToGL(m[SkMatrix::kMPersp1]);
        fMat[15] = SkPerspToGL(m[SkMatrix::kMPersp2]);

        fMat[10] = SK_GLScalar1;    // z-scale
    }
};

class SkGL {
public:
    static void SetColor(SkColor c);
    static void SetAlpha(U8CPU alpha);
    static void SetPaint(const SkPaint&, bool isPremul = true,
                         bool justAlpha = false);
    static void SetPaintAlpha(const SkPaint& paint, bool isPremul = true) {
        SetPaint(paint, isPremul, true);
    }

    static void SetRGBA(uint8_t rgba[], const SkColor src[], int count);
    static void DumpError(const char caller[]);
    
    static void Ortho(float left, float right, float bottom, float top,
                      float near, float far);

    static inline void Translate(SkScalar dx, SkScalar dy) {
        MAKE_GL(glTranslate)(SkScalarToGL(dx), SkScalarToGL(dy), 0);
    }
    
    static inline void Scale(SkScalar sx, SkScalar sy) {
        MAKE_GL(glScale)(SkScalarToGL(sx), SkScalarToGL(sy), SK_GLScalar1);
    }

    static inline void Rotate(SkScalar angle) {
        MAKE_GL(glRotate)(SkScalarToGL(angle), 0, 0, SK_GLScalar1);
    }

    static inline void MultMatrix(const SkMatrix& m) {
        SkGLMatrix glm;
        glm.set(m);
        MAKE_GL(glMultMatrix)(glm.fMat);
    }
    
    static inline void LoadMatrix(const SkMatrix& m) {
        SkGLMatrix glm;
        glm.set(m);
        MAKE_GL(glLoadMatrix)(glm.fMat);
    }
    
    static void Scissor(const SkIRect&, int viewportHeight);
    
    // return the byte size for the associated texture memory. This doesn't
    // always == bitmap.getSize(), since on a given port we may have to change
    // the format when the bitmap's pixels are copied over to GL
    static size_t ComputeTextureMemorySize(const SkBitmap&);
    // return 0 on failure
    static GLuint BindNewTexture(const SkBitmap&, SkPoint* dimension);

    static void SetTexParams(bool filter,
                             SkShader::TileMode tx, SkShader::TileMode ty);
    static void SetTexParamsClamp(bool filter);

    static void DrawVertices(int count, GLenum mode,
                             const SkGLVertex* SK_RESTRICT vertex,
                             const SkGLVertex* SK_RESTRICT texCoords,
                             const uint8_t* SK_RESTRICT colorArray,
                             const uint16_t* SK_RESTRICT indexArray,
                             SkGLClipIter*);
    
    static void PrepareForFillPath(SkPaint* paint);
    static void FillPath(const SkPath& path, const SkPaint& paint, bool useTex,
                         SkGLClipIter*);
    static void DrawPath(const SkPath& path, bool useTex, SkGLClipIter*);
};

#include "SkRegion.h"

class SkGLClipIter : public SkRegion::Iterator {
public:
    SkGLClipIter(int viewportHeight) : fViewportHeight(viewportHeight) {}
    
    // call rewind only if this is non-null
    void safeRewind() {
        if (this) {
            this->rewind();
        }
    }

    void scissor() {
        SkASSERT(!this->done());
        SkGL::Scissor(this->rect(), fViewportHeight);
    }
    
private:
    const int fViewportHeight;
};

#endif