Program.h revision 91a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0
15cbbce535744b89df5ecea95de21ee3733298260Romain Guy/*
25cbbce535744b89df5ecea95de21ee3733298260Romain Guy * Copyright (C) 2010 The Android Open Source Project
35cbbce535744b89df5ecea95de21ee3733298260Romain Guy *
45cbbce535744b89df5ecea95de21ee3733298260Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
55cbbce535744b89df5ecea95de21ee3733298260Romain Guy * you may not use this file except in compliance with the License.
65cbbce535744b89df5ecea95de21ee3733298260Romain Guy * You may obtain a copy of the License at
75cbbce535744b89df5ecea95de21ee3733298260Romain Guy *
85cbbce535744b89df5ecea95de21ee3733298260Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
95cbbce535744b89df5ecea95de21ee3733298260Romain Guy *
105cbbce535744b89df5ecea95de21ee3733298260Romain Guy * Unless required by applicable law or agreed to in writing, software
115cbbce535744b89df5ecea95de21ee3733298260Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
125cbbce535744b89df5ecea95de21ee3733298260Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135cbbce535744b89df5ecea95de21ee3733298260Romain Guy * See the License for the specific language governing permissions and
145cbbce535744b89df5ecea95de21ee3733298260Romain Guy * limitations under the License.
155cbbce535744b89df5ecea95de21ee3733298260Romain Guy */
165cbbce535744b89df5ecea95de21ee3733298260Romain Guy
175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#ifndef ANDROID_HWUI_PROGRAM_H
185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#define ANDROID_HWUI_PROGRAM_H
195cbbce535744b89df5ecea95de21ee3733298260Romain Guy
20f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#include <utils/KeyedVector.h>
21f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
225cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <GLES2/gl2.h>
235cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <GLES2/gl2ext.h>
245cbbce535744b89df5ecea95de21ee3733298260Romain Guy
25f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#include <SkXfermode.h>
265cbbce535744b89df5ecea95de21ee3733298260Romain Guy
27096b8d96d539429de5e67b2821ef3f9ee0300842Chris Craik#include "Debug.h"
280b9db91c3dc8007b47c8fd4fb9dd85be97201a88Romain Guy#include "Matrix.h"
29f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#include "Properties.h"
300b9db91c3dc8007b47c8fd4fb9dd85be97201a88Romain Guy
315cbbce535744b89df5ecea95de21ee3733298260Romain Guynamespace android {
325cbbce535744b89df5ecea95de21ee3733298260Romain Guynamespace uirenderer {
335cbbce535744b89df5ecea95de21ee3733298260Romain Guy
34f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy///////////////////////////////////////////////////////////////////////////////
35f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy// Defines
36f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy///////////////////////////////////////////////////////////////////////////////
37f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
38f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy// Debug
39f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#if DEBUG_PROGRAMS
405baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    #define PROGRAM_LOGD(...) ALOGD(__VA_ARGS__)
41f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#else
42f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    #define PROGRAM_LOGD(...)
43f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#endif
44f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
45f877308f77f7c6f3edd91618a092207dd3be9077Romain Guy#define COLOR_COMPONENT_THRESHOLD 1.0f
46f877308f77f7c6f3edd91618a092207dd3be9077Romain Guy#define COLOR_COMPONENT_INV_THRESHOLD 0.0f
47f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
48deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_TEXTURE             0x01
49deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_A8_TEXTURE          0x02
50deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_BITMAP              0x04
51deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_GRADIENT            0x08
52deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_BITMAP_FIRST        0x10
53deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_COLOR_MATRIX        0x20
54deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_COLOR_BLEND         0x40
55deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_BITMAP_NPOT         0x80
56deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
57deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_SWAP_SRC_DST      0x2000
58deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
59deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik#define PROGRAM_KEY_BITMAP_WRAPS_MASK  0x600
60f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
61f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
62f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy// Encode the xfermodes on 6 bits
63f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_MAX_XFERMODE 0x1f
64f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_XFERMODE_SHADER_SHIFT 26
65f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
66f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT 14
67f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
68f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_BITMAP_WRAPS_SHIFT 9
69f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_BITMAP_WRAPT_SHIFT 11
70f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
716d29c8d5218cac0fb35f3b7c253f2bdebd44f15aChris Craik#define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
72f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#define PROGRAM_MODULATE_SHIFT 35
73f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
7491a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik#define PROGRAM_HAS_VERTEX_ALPHA_SHIFT 36
7591a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik#define PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT 37
76f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
77bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
78bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
79f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
80bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_HAS_GAMMA_CORRECTION 40
81f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
82bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_IS_SIMPLE_GRADIENT 41
834121063313ac0d6f69f6253cac821d0c1c122086Romain Guy
84bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_HAS_COLORS 42
8542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
86bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43
87bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_EMULATE_STENCIL 44
88bf75945e7a1ae7c1000682716643c942c1e19ba6Chris Craik#define PROGRAM_HAS_ROUND_RECT_CLIP 45
893ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy
90f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy///////////////////////////////////////////////////////////////////////////////
91f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy// Types
92f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy///////////////////////////////////////////////////////////////////////////////
93f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
94f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guytypedef uint64_t programid;
95f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
96f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy///////////////////////////////////////////////////////////////////////////////
97f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy// Program description
98f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy///////////////////////////////////////////////////////////////////////////////
99f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
100f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy/**
101f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy * Describe the features required for a given program. The features
102f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy * determine the generation of both the vertex and fragment shaders.
103f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy * A ProgramDescription must be used in conjunction with a ProgramCache.
104f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy */
105f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guystruct ProgramDescription {
106f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    enum ColorModifier {
10742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        kColorNone = 0,
108f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        kColorMatrix,
109f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        kColorBlend
110f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    };
111f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
112f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    enum Gradient {
11342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        kGradientLinear = 0,
114f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        kGradientCircular,
115f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        kGradientSweep
116f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    };
117f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
118f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    ProgramDescription() {
119f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        reset();
120f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
121f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
122f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    // Texturing
123f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool hasTexture;
124f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool hasAlpha8Texture;
125f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool hasExternalTexture;
126f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool hasTextureTransform;
127f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
128ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy    // Color attribute
129ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy    bool hasColors;
130ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy
131f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    // Modulate, this should only be set when setColor() return true
132f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool modulate;
133f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
134f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    // Shaders
135f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool hasBitmap;
136f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool isBitmapNpot;
137f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
13891a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik    bool hasVertexAlpha;
13991a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik    bool useShadowAlphaInterp;
140f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
141f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool hasGradient;
142f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    Gradient gradientType;
14342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    bool isSimpleGradient;
144f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
145f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    SkXfermode::Mode shadersMode;
146f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
147f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool isBitmapFirst;
148f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    GLenum bitmapWrapS;
149f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    GLenum bitmapWrapT;
150f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
151f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    // Color operations
152f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    ColorModifier colorOp;
153f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    SkXfermode::Mode colorMode;
154f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
155f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    // Framebuffer blending (requires Extensions.hasFramebufferFetch())
156f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    // Ignored for all values < SkXfermode::kPlus_Mode
157f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    SkXfermode::Mode framebufferMode;
158f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    bool swapSrcDst;
159f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
1604121063313ac0d6f69f6253cac821d0c1c122086Romain Guy    bool hasGammaCorrection;
1614121063313ac0d6f69f6253cac821d0c1c122086Romain Guy    float gamma;
1624121063313ac0d6f69f6253cac821d0c1c122086Romain Guy
1633ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy    bool hasDebugHighlight;
16478dd96d5af20f489f0e8b288617d57774ec284f7Romain Guy    bool emulateStencil;
165deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    bool hasRoundRectClip;
1663ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy
167f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    /**
168f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * Resets this description. All fields are reset back to the default
169f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * values they hold after building a new instance.
170f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     */
171f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    void reset() {
172f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        hasTexture = false;
173f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        hasAlpha8Texture = false;
174f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        hasExternalTexture = false;
175f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        hasTextureTransform = false;
176f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
177ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        hasColors = false;
178ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy
17991a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik        hasVertexAlpha = false;
18091a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik        useShadowAlphaInterp = false;
181f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
182f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        modulate = false;
183f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
184f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        hasBitmap = false;
185f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        isBitmapNpot = false;
186f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
187f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        hasGradient = false;
188f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        gradientType = kGradientLinear;
18942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        isSimpleGradient = false;
190f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
191f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        shadersMode = SkXfermode::kClear_Mode;
192f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
193f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        isBitmapFirst = false;
194f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        bitmapWrapS = GL_CLAMP_TO_EDGE;
195f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        bitmapWrapT = GL_CLAMP_TO_EDGE;
196f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
197f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        colorOp = kColorNone;
198f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        colorMode = SkXfermode::kClear_Mode;
199f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
200f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        framebufferMode = SkXfermode::kClear_Mode;
201f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        swapSrcDst = false;
202f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
2034121063313ac0d6f69f6253cac821d0c1c122086Romain Guy        hasGammaCorrection = false;
2044121063313ac0d6f69f6253cac821d0c1c122086Romain Guy        gamma = 2.2f;
2053ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy
2063ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy        hasDebugHighlight = false;
207deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        emulateStencil = false;
208deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        hasRoundRectClip = false;
209f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
210f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
211f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    /**
212f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * Indicates, for a given color, whether color modulation is required in
213f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * the fragment shader. When this method returns true, the program should
214f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * be provided with a modulation color.
215f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     */
216e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik    bool setColorModulate(const float a) {
217a938f569ce206c1ed68d736181016b5b708c0084Romain Guy        modulate = a < COLOR_COMPONENT_THRESHOLD;
218f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        return modulate;
219f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
220f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
221f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    /**
222f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * Indicates, for a given color, whether color modulation is required in
223f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * the fragment shader. When this method returns true, the program should
224f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * be provided with a modulation color.
225f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     */
226e63f7c622a2086aefa80983c6f41b74fb166bb42Chris Craik    bool setAlpha8ColorModulate(const float r, const float g, const float b, const float a) {
227f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        modulate = a < COLOR_COMPONENT_THRESHOLD || r > COLOR_COMPONENT_INV_THRESHOLD ||
228f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                g > COLOR_COMPONENT_INV_THRESHOLD || b > COLOR_COMPONENT_INV_THRESHOLD;
229f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        return modulate;
230f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
231f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
232f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    /**
233f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * Computes the unique key identifying this program.
234f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     */
235f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    programid key() const {
236f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        programid key = 0;
237f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasTexture) key |= PROGRAM_KEY_TEXTURE;
238f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
239f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasBitmap) {
240f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            key |= PROGRAM_KEY_BITMAP;
241f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            if (isBitmapNpot) {
242f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                key |= PROGRAM_KEY_BITMAP_NPOT;
243f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
244f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
245f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            }
246f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        }
247f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
248f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
249f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
250f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasBitmap && hasGradient) {
251f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
252f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        }
253f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        switch (colorOp) {
254f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            case kColorMatrix:
255f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                key |= PROGRAM_KEY_COLOR_MATRIX;
256f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                break;
257f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            case kColorBlend:
258f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                key |= PROGRAM_KEY_COLOR_BLEND;
259f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
260f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                break;
261f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            case kColorNone:
262f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                break;
263f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        }
264f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
265f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
266f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
26791a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik        if (hasVertexAlpha) key |= programid(0x1) << PROGRAM_HAS_VERTEX_ALPHA_SHIFT;
26891a8c7c62913c2597e3bf5a6d59d2ed5fc7ba4e0Chris Craik        if (useShadowAlphaInterp) key |= programid(0x1) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT;
269f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
270f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
2714121063313ac0d6f69f6253cac821d0c1c122086Romain Guy        if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
27242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
273ff316ec7a76e52572a2e89b691e6b3bba0cafba3Romain Guy        if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
2743ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy        if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT;
27578dd96d5af20f489f0e8b288617d57774ec284f7Romain Guy        if (emulateStencil) key |= programid(0x1) << PROGRAM_EMULATE_STENCIL;
276deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        if (hasRoundRectClip) key |= programid(0x1) << PROGRAM_HAS_ROUND_RECT_CLIP;
277f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        return key;
278f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
279f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
280f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    /**
281f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * Logs the specified message followed by the key identifying this program.
282f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     */
283f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    void log(const char* message) const {
284f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#if DEBUG_PROGRAMS
285f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        programid k = key();
286f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
287f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                uint32_t(k & 0xffffffff));
288f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy#endif
289f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
290f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
291f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guyprivate:
2924121063313ac0d6f69f6253cac821d0c1c122086Romain Guy    static inline uint32_t getEnumForWrap(GLenum wrap) {
293f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        switch (wrap) {
294f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            case GL_CLAMP_TO_EDGE:
295f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                return 0;
296f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            case GL_REPEAT:
297f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                return 1;
298f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy            case GL_MIRRORED_REPEAT:
299f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy                return 2;
300f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        }
301f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy        return 0;
302f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    }
303f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
304f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy}; // struct ProgramDescription
305f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
3065cbbce535744b89df5ecea95de21ee3733298260Romain Guy/**
3075cbbce535744b89df5ecea95de21ee3733298260Romain Guy * A program holds a vertex and a fragment shader. It offers several utility
3085cbbce535744b89df5ecea95de21ee3733298260Romain Guy * methods to query attributes and uniforms.
3095cbbce535744b89df5ecea95de21ee3733298260Romain Guy */
310889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guyclass Program {
3115cbbce535744b89df5ecea95de21ee3733298260Romain Guypublic:
3123e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    enum ShaderBindings {
3133e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy        kBindingPosition,
3143e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy        kBindingTexCoords
3153e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    };
3163e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy
3175cbbce535744b89df5ecea95de21ee3733298260Romain Guy    /**
3185cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * Creates a new program with the specified vertex and fragment
3195cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * shaders sources.
3205cbbce535744b89df5ecea95de21ee3733298260Romain Guy     */
321f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    Program(const ProgramDescription& description, const char* vertex, const char* fragment);
3226926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    virtual ~Program();
3235cbbce535744b89df5ecea95de21ee3733298260Romain Guy
3245cbbce535744b89df5ecea95de21ee3733298260Romain Guy    /**
3255cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * Binds this program to the GL context.
3265cbbce535744b89df5ecea95de21ee3733298260Romain Guy     */
3276926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    virtual void use();
3285cbbce535744b89df5ecea95de21ee3733298260Romain Guy
329260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy    /**
330260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy     * Marks this program as unused. This will not unbind
331260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy     * the program from the GL context.
332260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy     */
3336926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy    virtual void remove();
334260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy
335260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy    /**
336ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy     * Returns the OpenGL name of the specified attribute.
337ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy     */
338ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    int getAttrib(const char* name);
339ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
340ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    /**
341ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy     * Returns the OpenGL name of the specified uniform.
342ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy     */
343ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    int getUniform(const char* name);
344ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy
345ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    /**
346260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy     * Indicates whether this program is currently in use with
347260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy     * the GL context.
348260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy     */
349260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy    inline bool isInUse() const {
350260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy        return mUse;
351260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy    }
352260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy
353889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    /**
35467f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy     * Indicates whether this program was correctly compiled and linked.
35567f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy     */
35667f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy    inline bool isInitialized() const {
35767f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy        return mInitialized;
35867f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy    }
35967f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy
36067f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy    /**
361889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     * Binds the program with the specified projection, modelView and
362889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     * transform matrices.
363889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     */
364889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
3658a5cc92a150bae38ec43732d941b38bb381fe153Chet Haase             const mat4& transformMatrix, bool offset = false);
366889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy
367889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    /**
368707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy     * Sets the color associated with this shader.
369889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     */
370707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy    void setColor(const float r, const float g, const float b, const float a);
371889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy
372889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    /**
373707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy     * Name of the position attribute.
374889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     */
375707b2f78ccaa09965d7e030fda3a883ce9b75ea8Romain Guy    int position;
376889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy
377889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    /**
378f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     * Name of the texCoords attribute if it exists, -1 otherwise.
379f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy     */
380f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    int texCoords;
381f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy
382f3a910b423db7ad79cf61518bdd9278c048ad0d8Romain Guy    /**
383889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     * Name of the transform uniform.
384889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy     */
385889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    int transform;
386889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy
38739284b763a09688468ed3799ebd2ebb76ea5dfd5Romain Guy    /**
38839284b763a09688468ed3799ebd2ebb76ea5dfd5Romain Guy     * Name of the projection uniform.
38939284b763a09688468ed3799ebd2ebb76ea5dfd5Romain Guy     */
39039284b763a09688468ed3799ebd2ebb76ea5dfd5Romain Guy    int projection;
39139284b763a09688468ed3799ebd2ebb76ea5dfd5Romain Guy
3925cbbce535744b89df5ecea95de21ee3733298260Romain Guyprotected:
3935cbbce535744b89df5ecea95de21ee3733298260Romain Guy    /**
3945cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * Adds an attribute with the specified name.
3955cbbce535744b89df5ecea95de21ee3733298260Romain Guy     *
3965cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * @return The OpenGL name of the attribute.
3975cbbce535744b89df5ecea95de21ee3733298260Romain Guy     */
3985cbbce535744b89df5ecea95de21ee3733298260Romain Guy    int addAttrib(const char* name);
3995cbbce535744b89df5ecea95de21ee3733298260Romain Guy
4005cbbce535744b89df5ecea95de21ee3733298260Romain Guy    /**
4013e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy     * Binds the specified attribute name to the specified slot.
4023e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy     */
4033e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    int bindAttrib(const char* name, ShaderBindings bindingSlot);
4043e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy
4053e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    /**
4065cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * Adds a uniform with the specified name.
4075cbbce535744b89df5ecea95de21ee3733298260Romain Guy     *
4085cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * @return The OpenGL name of the uniform.
4095cbbce535744b89df5ecea95de21ee3733298260Romain Guy     */
4105cbbce535744b89df5ecea95de21ee3733298260Romain Guy    int addUniform(const char* name);
4115cbbce535744b89df5ecea95de21ee3733298260Romain Guy
4125cbbce535744b89df5ecea95de21ee3733298260Romain Guyprivate:
4135cbbce535744b89df5ecea95de21ee3733298260Romain Guy    /**
4145cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * Compiles the specified shader of the specified type.
4155cbbce535744b89df5ecea95de21ee3733298260Romain Guy     *
4165cbbce535744b89df5ecea95de21ee3733298260Romain Guy     * @return The name of the compiled shader.
4175cbbce535744b89df5ecea95de21ee3733298260Romain Guy     */
4185cbbce535744b89df5ecea95de21ee3733298260Romain Guy    GLuint buildShader(const char* source, GLenum type);
4195cbbce535744b89df5ecea95de21ee3733298260Romain Guy
4203e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    // Name of the OpenGL program and shaders
42105bbde70fd2a3af737656b9f8c5a25b56429632eRomain Guy    GLuint mProgramId;
4223e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    GLuint mVertexShader;
4233e263fac8c9c0e0fb242186b514a7af8efb40961Romain Guy    GLuint mFragmentShader;
4245cbbce535744b89df5ecea95de21ee3733298260Romain Guy
4255cbbce535744b89df5ecea95de21ee3733298260Romain Guy    // Keeps track of attributes and uniforms slots
42605bbde70fd2a3af737656b9f8c5a25b56429632eRomain Guy    KeyedVector<const char*, int> mAttributes;
42705bbde70fd2a3af737656b9f8c5a25b56429632eRomain Guy    KeyedVector<const char*, int> mUniforms;
428260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy
429260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy    bool mUse;
43067f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy    bool mInitialized;
43105bbde70fd2a3af737656b9f8c5a25b56429632eRomain Guy
4323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    // Uniforms caching
43305bbde70fd2a3af737656b9f8c5a25b56429632eRomain Guy    bool mHasColorUniform;
43405bbde70fd2a3af737656b9f8c5a25b56429632eRomain Guy    int mColorUniform;
4352d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy
4362d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy    bool mHasSampler;
4373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
4383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    mat4 mProjection;
439d04a6b15f74035fd2068f34225825b55e94521f4Chris Craik    bool mOffset;
4405cbbce535744b89df5ecea95de21ee3733298260Romain Guy}; // class Program
4415cbbce535744b89df5ecea95de21ee3733298260Romain Guy
4425cbbce535744b89df5ecea95de21ee3733298260Romain Guy}; // namespace uirenderer
4435cbbce535744b89df5ecea95de21ee3733298260Romain Guy}; // namespace android
4445cbbce535744b89df5ecea95de21ee3733298260Romain Guy
4455b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_PROGRAM_H
446