13f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian/*
23f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * Copyright 2013 The Android Open Source Project
33f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian *
43f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
53f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * you may not use this file except in compliance with the License.
63f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * You may obtain a copy of the License at
73f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian *
83f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
93f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian *
103f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * Unless required by applicable law or agreed to in writing, software
113f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
123f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * See the License for the specific language governing permissions and
143f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * limitations under the License.
153f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian */
163f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
173f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian#include <GLES2/gl2.h>
183f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian#include <GLES2/gl2ext.h>
193f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
203f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian#include <utils/String8.h>
213f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
223f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian#include "ProgramCache.h"
233f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian#include "Program.h"
243f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian#include "Description.h"
253f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
263f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopiannamespace android {
273f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian// -----------------------------------------------------------------------------------------------
283f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
293f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
303f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian/*
313f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * A simple formatter class to automatically add the endl and
323f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian * manage the indentation.
333f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian */
343f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
353f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianclass Formatter;
363f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianstatic Formatter& indent(Formatter& f);
373f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianstatic Formatter& dedent(Formatter& f);
383f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
393f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianclass Formatter {
403f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    String8 mString;
413f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    int mIndent;
423f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    typedef Formatter& (*FormaterManipFunc)(Formatter&);
433f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    friend Formatter& indent(Formatter& f);
443f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    friend Formatter& dedent(Formatter& f);
453f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianpublic:
46892f22dcb96927b4a4f9ab7badd6f2c9f4f37c1fAndy McFadden    Formatter() : mIndent(0) {}
47892f22dcb96927b4a4f9ab7badd6f2c9f4f37c1fAndy McFadden
483f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    String8 getString() const {
493f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        return mString;
503f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
513f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
523f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    friend Formatter& operator << (Formatter& out, const char* in) {
533f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        for (int i=0 ; i<out.mIndent ; i++) {
543f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian            out.mString.append("    ");
553f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        }
563f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        out.mString.append(in);
573f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        out.mString.append("\n");
583f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        return out;
593f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
603f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    friend inline Formatter& operator << (Formatter& out, const String8& in) {
613f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        return operator << (out, in.string());
623f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
633f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
643f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        return (*func)(to);
653f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
663f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian};
673f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianFormatter& indent(Formatter& f) {
683f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    f.mIndent++;
693f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    return f;
703f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
713f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianFormatter& dedent(Formatter& f) {
723f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    f.mIndent--;
733f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    return f;
743f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
753f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
763f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian// -----------------------------------------------------------------------------------------------
773f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
783f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianANDROID_SINGLETON_STATIC_INSTANCE(ProgramCache)
793f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
803f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianProgramCache::ProgramCache() {
81a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    // Until surfaceflinger has a dependable blob cache on the filesystem,
82a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    // generate shaders on initialization so as to avoid jank.
83a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    primeCache();
843f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
853f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
863f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianProgramCache::~ProgramCache() {
873f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
883f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
89a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrewsvoid ProgramCache::primeCache() {
90a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    uint32_t shaderCount = 0;
91a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK |
92a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews                       Key::PLANE_ALPHA_MASK | Key::TEXTURE_MASK;
93a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    // Prime the cache for all combinations of the above masks,
94a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    // leaving off the experimental color matrix mask options.
95a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews
96a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    nsecs_t timeBefore = systemTime();
97a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    for (uint32_t keyVal = 0; keyVal <= keyMask; keyVal++) {
98a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        Key shaderKey;
99a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        shaderKey.set(keyMask, keyVal);
100a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        uint32_t tex = shaderKey.getTextureTarget();
101a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        if (tex != Key::TEXTURE_OFF &&
102a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews            tex != Key::TEXTURE_EXT &&
103a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews            tex != Key::TEXTURE_2D) {
104a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews            continue;
105a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        }
106a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        Program* program = mCache.valueFor(shaderKey);
107a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        if (program == NULL) {
108a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews            program = generateProgram(shaderKey);
109a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews            mCache.add(shaderKey, program);
110a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews            shaderCount++;
111a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews        }
112a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    }
113a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    nsecs_t timeAfter = systemTime();
114a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
115a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews    ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs);
116a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews}
117a51fafc4d83ab1d1582c1c870c31be44b057aa95Riley Andrews
1183f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianProgramCache::Key ProgramCache::computeKey(const Description& description) {
1193f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    Key needs;
1203f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    needs.set(Key::TEXTURE_MASK,
12149457ac092071a8f964f7f69156093657ccdc3d0Mathias Agopian            !description.mTextureEnabled ? Key::TEXTURE_OFF :
12249457ac092071a8f964f7f69156093657ccdc3d0Mathias Agopian            description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_EXT :
12349457ac092071a8f964f7f69156093657ccdc3d0Mathias Agopian            description.mTexture.getTextureTarget() == GL_TEXTURE_2D           ? Key::TEXTURE_2D :
1243f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian            Key::TEXTURE_OFF)
1253f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    .set(Key::PLANE_ALPHA_MASK,
1263f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian            (description.mPlaneAlpha < 1) ? Key::PLANE_ALPHA_LT_ONE : Key::PLANE_ALPHA_EQ_ONE)
1273f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    .set(Key::BLEND_MASK,
1283f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian            description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
1293f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    .set(Key::OPACITY_MASK,
130ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian            description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
131ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian    .set(Key::COLOR_MATRIX_MASK,
132ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian            description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON :  Key::COLOR_MATRIX_OFF);
1333f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    return needs;
1343f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
1353f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
1363f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianString8 ProgramCache::generateVertexShader(const Key& needs) {
1373f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    Formatter vs;
1383f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.isTexturing()) {
1393f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        vs  << "attribute vec4 texCoords;"
1403f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian            << "varying vec2 outTexCoords;";
1413f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
1423f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    vs << "attribute vec4 position;"
1433f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian       << "uniform mat4 projection;"
1443f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian       << "uniform mat4 texture;"
1453f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian       << "void main(void) {" << indent
1463f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian       << "gl_Position = projection * position;";
1473f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.isTexturing()) {
1483f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        vs << "outTexCoords = (texture * texCoords).st;";
1493f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
1503f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    vs << dedent << "}";
1513f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    return vs.getString();
1523f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
1533f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
1543f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianString8 ProgramCache::generateFragmentShader(const Key& needs) {
1553f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    Formatter fs;
1563f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
1573f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "#extension GL_OES_EGL_image_external : require";
1583f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
159458197de008be8fe561286b09f4edddb2f5c540aMathias Agopian
160458197de008be8fe561286b09f4edddb2f5c540aMathias Agopian    // default precision is required-ish in fragment shaders
161458197de008be8fe561286b09f4edddb2f5c540aMathias Agopian    fs << "precision mediump float;";
162458197de008be8fe561286b09f4edddb2f5c540aMathias Agopian
1633f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
1643f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "uniform samplerExternalOES sampler;"
1653f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian           << "varying vec2 outTexCoords;";
1663f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    } else if (needs.getTextureTarget() == Key::TEXTURE_2D) {
1673f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "uniform sampler2D sampler;"
1683f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian           << "varying vec2 outTexCoords;";
1693f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
1703f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "uniform vec4 color;";
1713f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
1723f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.hasPlaneAlpha()) {
1733f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "uniform float alphaPlane;";
1743f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
175ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian    if (needs.hasColorMatrix()) {
176ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        fs << "uniform mat4 colorMatrix;";
177ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian    }
1783f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    fs << "void main(void) {" << indent;
1793f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.isTexturing()) {
1803f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
1813f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    } else {
1823f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        fs << "gl_FragColor = color;";
1833f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
1842eaefe198a0cae1ee0b6366797a6b074c76df9efMathias Agopian    if (needs.isOpaque()) {
1852eaefe198a0cae1ee0b6366797a6b074c76df9efMathias Agopian        fs << "gl_FragColor.a = 1.0;";
1862eaefe198a0cae1ee0b6366797a6b074c76df9efMathias Agopian    }
1873f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (needs.hasPlaneAlpha()) {
1883f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        // modulate the alpha value with planeAlpha
1893f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        if (needs.isPremultiplied()) {
1903f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian            // ... and the color too if we're premultiplied
1912eaefe198a0cae1ee0b6366797a6b074c76df9efMathias Agopian            fs << "gl_FragColor *= alphaPlane;";
1923f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        } else {
1932eaefe198a0cae1ee0b6366797a6b074c76df9efMathias Agopian            fs << "gl_FragColor.a *= alphaPlane;";
1943f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        }
1953f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
196ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian
197ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian    if (needs.hasColorMatrix()) {
198ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        if (!needs.isOpaque() && needs.isPremultiplied()) {
199ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian            // un-premultiply if needed before linearization
200ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian            fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
201ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        }
202ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));";
203794c5ba973f6d107a8277f3f389cb3051c6ce5d7Alan Viverette        fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
204794c5ba973f6d107a8277f3f389cb3051c6ce5d7Alan Viverette        fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
205ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));";
206ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        if (!needs.isOpaque() && needs.isPremultiplied()) {
207ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian            // and re-premultiply if needed after gamma correction
208ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian            fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
209ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian        }
210ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian    }
211ff2ed70fa30f04b90dd1a2c06ec2319e157152d7Mathias Agopian
2123f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    fs << dedent << "}";
2133f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    return fs.getString();
2143f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
2153f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2163f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias AgopianProgram* ProgramCache::generateProgram(const Key& needs) {
2173f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    // vertex shader
2183f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    String8 vs = generateVertexShader(needs);
2193f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2203f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    // fragment shader
2213f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    String8 fs = generateFragmentShader(needs);
2223f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2233f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    Program* program = new Program(needs, vs.string(), fs.string());
2243f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    return program;
2253f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
2263f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2273f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopianvoid ProgramCache::useProgram(const Description& description) {
2283f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2293f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    // generate the key for the shader based on the description
2303f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    Key needs(computeKey(description));
2313f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2323f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian     // look-up the program in the cache
2333f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    Program* program = mCache.valueFor(needs);
2343f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (program == NULL) {
2353f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        // we didn't find our program, so generate one...
2363f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        nsecs_t time = -systemTime();
2373f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        program = generateProgram(needs);
2383f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        mCache.add(needs, program);
2393f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        time += systemTime();
2403f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2413f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        //ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
2423f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        //        needs.mNeeds, uint32_t(ns2ms(time)), mCache.size());
2433f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
2443f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2453f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    // here we have a suitable program for this description
2463f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    if (program->isValid()) {
2473f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        program->use();
2483f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian        program->setUniforms(description);
2493f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian    }
2503f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian}
2513f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2523f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian
2533f84483382be2d528918cc1a6fbc6a7d68e0b181Mathias Agopian} /* namespace android */
254