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