tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GLES1Renderer.cpp (48920B)


      1 //
      2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // GLES1Renderer.cpp: Implements the GLES1Renderer renderer.
      8 
      9 #include "libANGLE/GLES1Renderer.h"
     10 
     11 #include <string.h>
     12 #include <iterator>
     13 #include <sstream>
     14 #include <vector>
     15 
     16 #include "common/hash_utils.h"
     17 #include "libANGLE/Context.h"
     18 #include "libANGLE/Context.inl.h"
     19 #include "libANGLE/Program.h"
     20 #include "libANGLE/ResourceManager.h"
     21 #include "libANGLE/Shader.h"
     22 #include "libANGLE/State.h"
     23 #include "libANGLE/renderer/ContextImpl.h"
     24 
     25 namespace
     26 {
     27 #include "libANGLE/GLES1Shaders.inc"
     28 
     29 uint32_t GetLogicOpUniform(const gl::FramebufferAttachment *color, gl::LogicalOperation logicOp)
     30 {
     31    const uint32_t red   = color->getRedSize();
     32    const uint32_t green = color->getGreenSize();
     33    const uint32_t blue  = color->getBlueSize();
     34    const uint32_t alpha = color->getAlphaSize();
     35 
     36    ASSERT(red <= 8 && green <= 8 && blue <= 8 && alpha <= 8);
     37 
     38    return red | green << 4 | blue << 8 | alpha << 12 | static_cast<uint32_t>(logicOp) << 16;
     39 }
     40 }  // anonymous namespace
     41 
     42 namespace gl
     43 {
     44 GLES1ShaderState::GLES1ShaderState()  = default;
     45 GLES1ShaderState::~GLES1ShaderState() = default;
     46 GLES1ShaderState::GLES1ShaderState(const GLES1ShaderState &other)
     47 {
     48    memcpy(this, &other, sizeof(GLES1ShaderState));
     49 }
     50 
     51 bool operator==(const GLES1ShaderState &a, const GLES1ShaderState &b)
     52 {
     53    return memcmp(&a, &b, sizeof(GLES1ShaderState)) == 0;
     54 }
     55 bool operator!=(const GLES1ShaderState &a, const GLES1ShaderState &b)
     56 {
     57    return !(a == b);
     58 }
     59 
     60 size_t GLES1ShaderState::hash() const
     61 {
     62    return angle::ComputeGenericHash(*this);
     63 }
     64 
     65 GLES1Renderer::GLES1Renderer() : mRendererProgramInitialized(false) {}
     66 
     67 void GLES1Renderer::onDestroy(Context *context, State *state)
     68 {
     69    if (mRendererProgramInitialized)
     70    {
     71        (void)state->setProgram(context, 0);
     72 
     73        for (const auto &iter : mUberShaderState)
     74        {
     75            const GLES1UberShaderState &UberShaderState = iter.second;
     76            mShaderPrograms->deleteProgram(context, {UberShaderState.programState.program});
     77        }
     78        mShaderPrograms->release(context);
     79        mShaderPrograms             = nullptr;
     80        mRendererProgramInitialized = false;
     81    }
     82 }
     83 
     84 GLES1Renderer::~GLES1Renderer() = default;
     85 
     86 angle::Result GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State *glState)
     87 {
     88    GLES1State &gles1State = glState->gles1();
     89 
     90    GLES1ShaderState::BoolTexArray &tex2DEnables   = mShaderState.tex2DEnables;
     91    GLES1ShaderState::BoolTexArray &texCubeEnables = mShaderState.texCubeEnables;
     92    GLES1ShaderState::IntTexArray &tex2DFormats    = mShaderState.tex2DFormats;
     93 
     94    for (int i = 0; i < kTexUnitCount; i++)
     95    {
     96        // GL_OES_cube_map allows only one of TEXTURE_2D / TEXTURE_CUBE_MAP
     97        // to be enabled per unit, thankfully. From the extension text:
     98        //
     99        //  --  Section 3.8.10 "Texture Application"
    100        //
    101        //      Replace the beginning sentences of the first paragraph (page 138)
    102        //      with:
    103        //
    104        //      "Texturing is enabled or disabled using the generic Enable
    105        //      and Disable commands, respectively, with the symbolic constants
    106        //      TEXTURE_2D or TEXTURE_CUBE_MAP_OES to enable the two-dimensional or cube
    107        //      map texturing respectively.  If the cube map texture and the two-
    108        //      dimensional texture are enabled, then cube map texturing is used.  If
    109        //      texturing is disabled, a rasterized fragment is passed on unaltered to the
    110        //      next stage of the GL (although its texture coordinates may be discarded).
    111        //      Otherwise, a texture value is found according to the parameter values of
    112        //      the currently bound texture image of the appropriate dimensionality.
    113 
    114        texCubeEnables[i] = gles1State.isTextureTargetEnabled(i, TextureType::CubeMap);
    115        tex2DEnables[i] =
    116            !texCubeEnables[i] && gles1State.isTextureTargetEnabled(i, TextureType::_2D);
    117 
    118        Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D);
    119        if (curr2DTexture)
    120        {
    121            tex2DFormats[i] = gl::GetUnsizedFormat(
    122                curr2DTexture->getFormat(TextureTarget::_2D, 0).info->internalFormat);
    123        }
    124 
    125        Texture *currCubeTexture = glState->getSamplerTexture(i, TextureType::CubeMap);
    126 
    127        // > If texturing is enabled for a texture unit at the time a primitive is rasterized, if
    128        // > TEXTURE MIN FILTER is one that requires a mipmap, and if the texture image bound to the
    129        // > enabled texture target is not complete, then it is as if texture mapping were disabled
    130        // > for that texture unit.
    131        if (tex2DEnables[i] && curr2DTexture && IsMipmapFiltered(curr2DTexture->getMinFilter()))
    132        {
    133            tex2DEnables[i] = curr2DTexture->isMipmapComplete();
    134        }
    135        if (texCubeEnables[i] && currCubeTexture &&
    136            IsMipmapFiltered(currCubeTexture->getMinFilter()))
    137        {
    138            texCubeEnables[i] = curr2DTexture->isMipmapComplete();
    139        }
    140    }
    141 
    142    GLES1ShaderState::IntTexArray &texEnvModes          = mShaderState.texEnvModes;
    143    GLES1ShaderState::IntTexArray &texCombineRgbs       = mShaderState.texCombineRgbs;
    144    GLES1ShaderState::IntTexArray &texCombineAlphas     = mShaderState.texCombineAlphas;
    145    GLES1ShaderState::IntTexArray &texCombineSrc0Rgbs   = mShaderState.texCombineSrc0Rgbs;
    146    GLES1ShaderState::IntTexArray &texCombineSrc0Alphas = mShaderState.texCombineSrc0Alphas;
    147    GLES1ShaderState::IntTexArray &texCombineSrc1Rgbs   = mShaderState.texCombineSrc1Rgbs;
    148    GLES1ShaderState::IntTexArray &texCombineSrc1Alphas = mShaderState.texCombineSrc1Alphas;
    149    GLES1ShaderState::IntTexArray &texCombineSrc2Rgbs   = mShaderState.texCombineSrc2Rgbs;
    150    GLES1ShaderState::IntTexArray &texCombineSrc2Alphas = mShaderState.texCombineSrc2Alphas;
    151    GLES1ShaderState::IntTexArray &texCombineOp0Rgbs    = mShaderState.texCombineOp0Rgbs;
    152    GLES1ShaderState::IntTexArray &texCombineOp0Alphas  = mShaderState.texCombineOp0Alphas;
    153    GLES1ShaderState::IntTexArray &texCombineOp1Rgbs    = mShaderState.texCombineOp1Rgbs;
    154    GLES1ShaderState::IntTexArray &texCombineOp1Alphas  = mShaderState.texCombineOp1Alphas;
    155    GLES1ShaderState::IntTexArray &texCombineOp2Rgbs    = mShaderState.texCombineOp2Rgbs;
    156    GLES1ShaderState::IntTexArray &texCombineOp2Alphas  = mShaderState.texCombineOp2Alphas;
    157 
    158    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_TEXTURE_ENVIRONMENT))
    159    {
    160        for (int i = 0; i < kTexUnitCount; i++)
    161        {
    162            const auto &env         = gles1State.textureEnvironment(i);
    163            texEnvModes[i]          = ToGLenum(env.mode);
    164            texCombineRgbs[i]       = ToGLenum(env.combineRgb);
    165            texCombineAlphas[i]     = ToGLenum(env.combineAlpha);
    166            texCombineSrc0Rgbs[i]   = ToGLenum(env.src0Rgb);
    167            texCombineSrc0Alphas[i] = ToGLenum(env.src0Alpha);
    168            texCombineSrc1Rgbs[i]   = ToGLenum(env.src1Rgb);
    169            texCombineSrc1Alphas[i] = ToGLenum(env.src1Alpha);
    170            texCombineSrc2Rgbs[i]   = ToGLenum(env.src2Rgb);
    171            texCombineSrc2Alphas[i] = ToGLenum(env.src2Alpha);
    172            texCombineOp0Rgbs[i]    = ToGLenum(env.op0Rgb);
    173            texCombineOp0Alphas[i]  = ToGLenum(env.op0Alpha);
    174            texCombineOp1Rgbs[i]    = ToGLenum(env.op1Rgb);
    175            texCombineOp1Alphas[i]  = ToGLenum(env.op1Alpha);
    176            texCombineOp2Rgbs[i]    = ToGLenum(env.op2Rgb);
    177            texCombineOp2Alphas[i]  = ToGLenum(env.op2Alpha);
    178        }
    179    }
    180 
    181    bool enableClipPlanes                                  = false;
    182    GLES1ShaderState::BoolClipPlaneArray &clipPlaneEnables = mShaderState.clipPlaneEnables;
    183    for (int i = 0; i < kClipPlaneCount; i++)
    184    {
    185        clipPlaneEnables[i] = glState->getEnableFeature(GL_CLIP_PLANE0 + i);
    186        enableClipPlanes    = enableClipPlanes || clipPlaneEnables[i];
    187    }
    188 
    189    mShaderState.mGLES1StateEnabled[GLES1StateEnables::ClipPlanes]  = enableClipPlanes;
    190    mShaderState.mGLES1StateEnabled[GLES1StateEnables::DrawTexture] = mDrawTextureEnabled;
    191    mShaderState.mGLES1StateEnabled[GLES1StateEnables::PointRasterization] =
    192        mode == PrimitiveMode::Points;
    193    mShaderState.mGLES1StateEnabled[GLES1StateEnables::ShadeModelFlat] =
    194        gles1State.mShadeModel == ShadingModel::Flat;
    195    mShaderState.mGLES1StateEnabled[GLES1StateEnables::AlphaTest] =
    196        glState->getEnableFeature(GL_ALPHA_TEST);
    197    mShaderState.mGLES1StateEnabled[GLES1StateEnables::Lighting] =
    198        glState->getEnableFeature(GL_LIGHTING);
    199    mShaderState.mGLES1StateEnabled[GLES1StateEnables::RescaleNormal] =
    200        glState->getEnableFeature(GL_RESCALE_NORMAL);
    201    mShaderState.mGLES1StateEnabled[GLES1StateEnables::Normalize] =
    202        glState->getEnableFeature(GL_NORMALIZE);
    203    mShaderState.mGLES1StateEnabled[GLES1StateEnables::Fog] = glState->getEnableFeature(GL_FOG);
    204    mShaderState.mGLES1StateEnabled[GLES1StateEnables::PointSprite] =
    205        glState->getEnableFeature(GL_POINT_SPRITE_OES);
    206    mShaderState.mGLES1StateEnabled[GLES1StateEnables::ColorMaterial] =
    207        glState->getEnableFeature(GL_COLOR_MATERIAL);
    208 
    209    // TODO (lfy@google.com): Implement two-sided lighting model (lightModel.twoSided)
    210    mShaderState.mGLES1StateEnabled[GLES1StateEnables::LightModelTwoSided] = false;
    211 
    212    GLES1ShaderState::BoolTexArray &pointSpriteCoordReplaces =
    213        mShaderState.pointSpriteCoordReplaces;
    214    for (int i = 0; i < kTexUnitCount; i++)
    215    {
    216        const auto &env             = gles1State.textureEnvironment(i);
    217        pointSpriteCoordReplaces[i] = env.pointSpriteCoordReplace;
    218    }
    219 
    220    GLES1ShaderState::BoolLightArray &lightEnables = mShaderState.lightEnables;
    221    for (int i = 0; i < kLightCount; i++)
    222    {
    223        const auto &light = gles1State.mLights[i];
    224        lightEnables[i]   = light.enabled;
    225    }
    226 
    227    mShaderState.alphaTestFunc = gles1State.mAlphaTestFunc;
    228    mShaderState.fogMode       = gles1State.fogParameters().mode;
    229 
    230    const bool hasLogicOpANGLE     = context->getExtensions().logicOpANGLE;
    231    const bool hasFramebufferFetch = context->getExtensions().shaderFramebufferFetchEXT ||
    232                                     context->getExtensions().shaderFramebufferFetchNonCoherentEXT;
    233 
    234    if (!hasLogicOpANGLE && hasFramebufferFetch)
    235    {
    236        mShaderState.mGLES1StateEnabled[GLES1StateEnables::LogicOpThroughFramebufferFetch] =
    237            gles1State.mLogicOpEnabled;
    238    }
    239 
    240    // All the states set before this spot affect ubershader creation
    241 
    242    ANGLE_TRY(initializeRendererProgram(context, glState));
    243 
    244    GLES1UberShaderState UberShaderState = getUberShaderState();
    245 
    246    const GLES1ProgramState &programState = UberShaderState.programState;
    247    GLES1UniformBuffers &uniformBuffers   = UberShaderState.uniformBuffers;
    248 
    249    Program *programObject = getProgram(programState.program);
    250 
    251    // If anything is dirty in gles1 or the common parts of gles1/2, just redo these parts
    252    // completely for now.
    253 
    254    // Feature enables
    255 
    256    // Texture unit enables and format info
    257    std::array<Vec4Uniform, kTexUnitCount> texCropRects;
    258    Vec4Uniform *cropRectBuffer = texCropRects.data();
    259    for (int i = 0; i < kTexUnitCount; i++)
    260    {
    261        Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D);
    262        if (curr2DTexture)
    263        {
    264            const gl::Rectangle &cropRect = curr2DTexture->getCrop();
    265 
    266            GLfloat textureWidth =
    267                static_cast<GLfloat>(curr2DTexture->getWidth(TextureTarget::_2D, 0));
    268            GLfloat textureHeight =
    269                static_cast<GLfloat>(curr2DTexture->getHeight(TextureTarget::_2D, 0));
    270 
    271            if (textureWidth > 0.0f && textureHeight > 0.0f)
    272            {
    273                cropRectBuffer[i][0] = cropRect.x / textureWidth;
    274                cropRectBuffer[i][1] = cropRect.y / textureHeight;
    275                cropRectBuffer[i][2] = cropRect.width / textureWidth;
    276                cropRectBuffer[i][3] = cropRect.height / textureHeight;
    277            }
    278        }
    279    }
    280    setUniform4fv(programObject, programState.drawTextureNormalizedCropRectLoc, kTexUnitCount,
    281                  reinterpret_cast<GLfloat *>(cropRectBuffer));
    282 
    283    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LOGIC_OP) && hasLogicOpANGLE)
    284    {
    285        context->setLogicOpEnabled(gles1State.mLogicOpEnabled);
    286        context->setLogicOp(gles1State.mLogicOp);
    287    }
    288    else if (hasFramebufferFetch)
    289    {
    290        const Framebuffer *drawFramebuffer           = glState->getDrawFramebuffer();
    291        const FramebufferAttachment *colorAttachment = drawFramebuffer->getColorAttachment(0);
    292 
    293        if (gles1State.mLogicOpEnabled)
    294        {
    295            if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LOGIC_OP))
    296            {
    297                // Set up uniform value for logic op
    298                setUniform1ui(programObject, programState.logicOpLoc,
    299                              GetLogicOpUniform(colorAttachment, gles1State.mLogicOp));
    300            }
    301 
    302            // Issue a framebuffer fetch barrier if non-coherent
    303            if (!context->getExtensions().shaderFramebufferFetchEXT)
    304            {
    305                context->framebufferFetchBarrier();
    306            }
    307        }
    308    }
    309 
    310    // Client state / current vector enables
    311    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_CLIENT_STATE_ENABLE) ||
    312        gles1State.isDirty(GLES1State::DIRTY_GLES1_CURRENT_VECTOR))
    313    {
    314        if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Normal))
    315        {
    316            const angle::Vector3 normal = gles1State.getCurrentNormal();
    317            context->vertexAttrib3f(kNormalAttribIndex, normal.x(), normal.y(), normal.z());
    318        }
    319 
    320        if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Color))
    321        {
    322            const ColorF color = gles1State.getCurrentColor();
    323            context->vertexAttrib4f(kColorAttribIndex, color.red, color.green, color.blue,
    324                                    color.alpha);
    325        }
    326 
    327        if (!gles1State.isClientStateEnabled(ClientVertexArrayType::PointSize))
    328        {
    329            GLfloat pointSize = gles1State.mPointParameters.pointSize;
    330            context->vertexAttrib1f(kPointSizeAttribIndex, pointSize);
    331        }
    332 
    333        for (int i = 0; i < kTexUnitCount; i++)
    334        {
    335            if (!gles1State.mTexCoordArrayEnabled[i])
    336            {
    337                const TextureCoordF texcoord = gles1State.getCurrentTextureCoords(i);
    338                context->vertexAttrib4f(kTextureCoordAttribIndexBase + i, texcoord.s, texcoord.t,
    339                                        texcoord.r, texcoord.q);
    340            }
    341        }
    342    }
    343 
    344    // Matrices
    345    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_MATRICES))
    346    {
    347        angle::Mat4 proj = gles1State.mProjectionMatrices.back();
    348        setUniformMatrix4fv(programObject, programState.projMatrixLoc, 1, GL_FALSE, proj.data());
    349 
    350        angle::Mat4 modelview = gles1State.mModelviewMatrices.back();
    351        setUniformMatrix4fv(programObject, programState.modelviewMatrixLoc, 1, GL_FALSE,
    352                            modelview.data());
    353 
    354        angle::Mat4 modelviewInvTr = modelview.transpose().inverse();
    355        setUniformMatrix4fv(programObject, programState.modelviewInvTrLoc, 1, GL_FALSE,
    356                            modelviewInvTr.data());
    357 
    358        Mat4Uniform *textureMatrixBuffer = uniformBuffers.textureMatrices.data();
    359 
    360        for (int i = 0; i < kTexUnitCount; i++)
    361        {
    362            angle::Mat4 textureMatrix = gles1State.mTextureMatrices[i].back();
    363            memcpy(textureMatrixBuffer + i, textureMatrix.data(), sizeof(Mat4Uniform));
    364        }
    365 
    366        setUniformMatrix4fv(programObject, programState.textureMatrixLoc, kTexUnitCount, GL_FALSE,
    367                            reinterpret_cast<float *>(uniformBuffers.textureMatrices.data()));
    368    }
    369 
    370    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_TEXTURE_ENVIRONMENT))
    371    {
    372        for (int i = 0; i < kTexUnitCount; i++)
    373        {
    374            const auto &env = gles1State.textureEnvironment(i);
    375 
    376            uniformBuffers.texEnvColors[i][0] = env.color.red;
    377            uniformBuffers.texEnvColors[i][1] = env.color.green;
    378            uniformBuffers.texEnvColors[i][2] = env.color.blue;
    379            uniformBuffers.texEnvColors[i][3] = env.color.alpha;
    380 
    381            uniformBuffers.texEnvRgbScales[i]   = env.rgbScale;
    382            uniformBuffers.texEnvAlphaScales[i] = env.alphaScale;
    383        }
    384 
    385        setUniform4fv(programObject, programState.textureEnvColorLoc, kTexUnitCount,
    386                      reinterpret_cast<float *>(uniformBuffers.texEnvColors.data()));
    387        setUniform1fv(programObject, programState.rgbScaleLoc, kTexUnitCount,
    388                      uniformBuffers.texEnvRgbScales.data());
    389        setUniform1fv(programObject, programState.alphaScaleLoc, kTexUnitCount,
    390                      uniformBuffers.texEnvAlphaScales.data());
    391    }
    392 
    393    // Alpha test
    394    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_ALPHA_TEST))
    395    {
    396        setUniform1f(programObject, programState.alphaTestRefLoc, gles1State.mAlphaTestRef);
    397    }
    398 
    399    // Shading, materials, and lighting
    400    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_MATERIAL))
    401    {
    402        const auto &material = gles1State.mMaterial;
    403 
    404        setUniform4fv(programObject, programState.materialAmbientLoc, 1, material.ambient.data());
    405        setUniform4fv(programObject, programState.materialDiffuseLoc, 1, material.diffuse.data());
    406        setUniform4fv(programObject, programState.materialSpecularLoc, 1, material.specular.data());
    407        setUniform4fv(programObject, programState.materialEmissiveLoc, 1, material.emissive.data());
    408        setUniform1f(programObject, programState.materialSpecularExponentLoc,
    409                     material.specularExponent);
    410    }
    411 
    412    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LIGHTS))
    413    {
    414        const auto &lightModel = gles1State.mLightModel;
    415 
    416        setUniform4fv(programObject, programState.lightModelSceneAmbientLoc, 1,
    417                      lightModel.color.data());
    418 
    419        for (int i = 0; i < kLightCount; i++)
    420        {
    421            const auto &light = gles1State.mLights[i];
    422            memcpy(uniformBuffers.lightAmbients.data() + i, light.ambient.data(),
    423                   sizeof(Vec4Uniform));
    424            memcpy(uniformBuffers.lightDiffuses.data() + i, light.diffuse.data(),
    425                   sizeof(Vec4Uniform));
    426            memcpy(uniformBuffers.lightSpeculars.data() + i, light.specular.data(),
    427                   sizeof(Vec4Uniform));
    428            memcpy(uniformBuffers.lightPositions.data() + i, light.position.data(),
    429                   sizeof(Vec4Uniform));
    430            memcpy(uniformBuffers.lightDirections.data() + i, light.direction.data(),
    431                   sizeof(Vec3Uniform));
    432            uniformBuffers.spotlightExponents[i]    = light.spotlightExponent;
    433            uniformBuffers.spotlightCutoffAngles[i] = light.spotlightCutoffAngle;
    434            uniformBuffers.attenuationConsts[i]     = light.attenuationConst;
    435            uniformBuffers.attenuationLinears[i]    = light.attenuationLinear;
    436            uniformBuffers.attenuationQuadratics[i] = light.attenuationQuadratic;
    437        }
    438 
    439        setUniform4fv(programObject, programState.lightAmbientsLoc, kLightCount,
    440                      reinterpret_cast<float *>(uniformBuffers.lightAmbients.data()));
    441        setUniform4fv(programObject, programState.lightDiffusesLoc, kLightCount,
    442                      reinterpret_cast<float *>(uniformBuffers.lightDiffuses.data()));
    443        setUniform4fv(programObject, programState.lightSpecularsLoc, kLightCount,
    444                      reinterpret_cast<float *>(uniformBuffers.lightSpeculars.data()));
    445        setUniform4fv(programObject, programState.lightPositionsLoc, kLightCount,
    446                      reinterpret_cast<float *>(uniformBuffers.lightPositions.data()));
    447        setUniform3fv(programObject, programState.lightDirectionsLoc, kLightCount,
    448                      reinterpret_cast<float *>(uniformBuffers.lightDirections.data()));
    449        setUniform1fv(programObject, programState.lightSpotlightExponentsLoc, kLightCount,
    450                      reinterpret_cast<float *>(uniformBuffers.spotlightExponents.data()));
    451        setUniform1fv(programObject, programState.lightSpotlightCutoffAnglesLoc, kLightCount,
    452                      reinterpret_cast<float *>(uniformBuffers.spotlightCutoffAngles.data()));
    453        setUniform1fv(programObject, programState.lightAttenuationConstsLoc, kLightCount,
    454                      reinterpret_cast<float *>(uniformBuffers.attenuationConsts.data()));
    455        setUniform1fv(programObject, programState.lightAttenuationLinearsLoc, kLightCount,
    456                      reinterpret_cast<float *>(uniformBuffers.attenuationLinears.data()));
    457        setUniform1fv(programObject, programState.lightAttenuationQuadraticsLoc, kLightCount,
    458                      reinterpret_cast<float *>(uniformBuffers.attenuationQuadratics.data()));
    459    }
    460 
    461    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_FOG))
    462    {
    463        const FogParameters &fog = gles1State.fogParameters();
    464        setUniform1f(programObject, programState.fogDensityLoc, fog.density);
    465        setUniform1f(programObject, programState.fogStartLoc, fog.start);
    466        setUniform1f(programObject, programState.fogEndLoc, fog.end);
    467        setUniform4fv(programObject, programState.fogColorLoc, 1, fog.color.data());
    468    }
    469 
    470    // Clip planes
    471    if (gles1State.isDirty(GLES1State::DIRTY_GLES1_CLIP_PLANES))
    472    {
    473        for (int i = 0; i < kClipPlaneCount; i++)
    474        {
    475            gles1State.getClipPlane(
    476                i, reinterpret_cast<float *>(uniformBuffers.clipPlanes.data() + i));
    477        }
    478 
    479        setUniform4fv(programObject, programState.clipPlanesLoc, kClipPlaneCount,
    480                      reinterpret_cast<float *>(uniformBuffers.clipPlanes.data()));
    481    }
    482 
    483    // Point rasterization
    484    {
    485        const PointParameters &pointParams = gles1State.mPointParameters;
    486 
    487        setUniform1f(programObject, programState.pointSizeMinLoc, pointParams.pointSizeMin);
    488        setUniform1f(programObject, programState.pointSizeMaxLoc, pointParams.pointSizeMax);
    489        setUniform3fv(programObject, programState.pointDistanceAttenuationLoc, 1,
    490                      pointParams.pointDistanceAttenuation.data());
    491    }
    492 
    493    // Draw texture
    494    {
    495        setUniform4fv(programObject, programState.drawTextureCoordsLoc, 1, mDrawTextureCoords);
    496        setUniform2fv(programObject, programState.drawTextureDimsLoc, 1, mDrawTextureDims);
    497    }
    498 
    499    gles1State.clearDirty();
    500 
    501    // None of those are changes in sampler, so there is no need to set the GL_PROGRAM dirty.
    502    // Otherwise, put the dirtying here.
    503 
    504    return angle::Result::Continue;
    505 }
    506 
    507 // static
    508 int GLES1Renderer::VertexArrayIndex(ClientVertexArrayType type, const GLES1State &gles1)
    509 {
    510    switch (type)
    511    {
    512        case ClientVertexArrayType::Vertex:
    513            return kVertexAttribIndex;
    514        case ClientVertexArrayType::Normal:
    515            return kNormalAttribIndex;
    516        case ClientVertexArrayType::Color:
    517            return kColorAttribIndex;
    518        case ClientVertexArrayType::PointSize:
    519            return kPointSizeAttribIndex;
    520        case ClientVertexArrayType::TextureCoord:
    521            return kTextureCoordAttribIndexBase + gles1.getClientTextureUnit();
    522        default:
    523            UNREACHABLE();
    524            return 0;
    525    }
    526 }
    527 
    528 // static
    529 ClientVertexArrayType GLES1Renderer::VertexArrayType(int attribIndex)
    530 {
    531    switch (attribIndex)
    532    {
    533        case kVertexAttribIndex:
    534            return ClientVertexArrayType::Vertex;
    535        case kNormalAttribIndex:
    536            return ClientVertexArrayType::Normal;
    537        case kColorAttribIndex:
    538            return ClientVertexArrayType::Color;
    539        case kPointSizeAttribIndex:
    540            return ClientVertexArrayType::PointSize;
    541        default:
    542            if (attribIndex < kTextureCoordAttribIndexBase + kTexUnitCount)
    543            {
    544                return ClientVertexArrayType::TextureCoord;
    545            }
    546            UNREACHABLE();
    547            return ClientVertexArrayType::InvalidEnum;
    548    }
    549 }
    550 
    551 // static
    552 int GLES1Renderer::TexCoordArrayIndex(unsigned int unit)
    553 {
    554    return kTextureCoordAttribIndexBase + unit;
    555 }
    556 
    557 void GLES1Renderer::drawTexture(Context *context,
    558                                State *glState,
    559                                float x,
    560                                float y,
    561                                float z,
    562                                float width,
    563                                float height)
    564 {
    565 
    566    // get viewport
    567    const gl::Rectangle &viewport = glState->getViewport();
    568 
    569    // Translate from viewport to NDC for feeding the shader.
    570    // Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1])
    571    float xNdc = scaleScreenCoordinateToNdc(x, static_cast<GLfloat>(viewport.width));
    572    float yNdc = scaleScreenCoordinateToNdc(y, static_cast<GLfloat>(viewport.height));
    573    float wNdc = scaleScreenDimensionToNdc(width, static_cast<GLfloat>(viewport.width));
    574    float hNdc = scaleScreenDimensionToNdc(height, static_cast<GLfloat>(viewport.height));
    575 
    576    float zNdc = 2.0f * clamp(z, 0.0f, 1.0f) - 1.0f;
    577 
    578    mDrawTextureCoords[0] = xNdc;
    579    mDrawTextureCoords[1] = yNdc;
    580    mDrawTextureCoords[2] = zNdc;
    581 
    582    mDrawTextureDims[0] = wNdc;
    583    mDrawTextureDims[1] = hNdc;
    584 
    585    mDrawTextureEnabled = true;
    586 
    587    AttributesMask prevAttributesMask = glState->gles1().getVertexArraysAttributeMask();
    588 
    589    setAttributesEnabled(context, glState, AttributesMask());
    590 
    591    glState->gles1().setAllDirty();
    592 
    593    context->drawArrays(PrimitiveMode::Triangles, 0, 6);
    594 
    595    setAttributesEnabled(context, glState, prevAttributesMask);
    596 
    597    mDrawTextureEnabled = false;
    598 }
    599 
    600 Shader *GLES1Renderer::getShader(ShaderProgramID handle) const
    601 {
    602    return mShaderPrograms->getShader(handle);
    603 }
    604 
    605 Program *GLES1Renderer::getProgram(ShaderProgramID handle) const
    606 {
    607    return mShaderPrograms->getProgram(handle);
    608 }
    609 
    610 angle::Result GLES1Renderer::compileShader(Context *context,
    611                                           ShaderType shaderType,
    612                                           const char *src,
    613                                           ShaderProgramID *shaderOut)
    614 {
    615    rx::ContextImpl *implementation = context->getImplementation();
    616    const Limitations &limitations  = implementation->getNativeLimitations();
    617 
    618    ShaderProgramID shader = mShaderPrograms->createShader(implementation, limitations, shaderType);
    619 
    620    Shader *shaderObject = getShader(shader);
    621    ANGLE_CHECK(context, shaderObject, "Missing shader object", GL_INVALID_OPERATION);
    622 
    623    shaderObject->setSource(1, &src, nullptr);
    624    shaderObject->compile(context);
    625 
    626    *shaderOut = shader;
    627 
    628    if (!shaderObject->isCompiled(context))
    629    {
    630        GLint infoLogLength = shaderObject->getInfoLogLength(context);
    631        std::vector<char> infoLog(infoLogLength, 0);
    632        shaderObject->getInfoLog(context, infoLogLength - 1, nullptr, infoLog.data());
    633 
    634        ERR() << "Internal GLES 1 shader compile failed. Info log: " << infoLog.data();
    635        ANGLE_CHECK(context, false, "GLES1Renderer shader compile failed.", GL_INVALID_OPERATION);
    636        return angle::Result::Stop;
    637    }
    638 
    639    return angle::Result::Continue;
    640 }
    641 
    642 angle::Result GLES1Renderer::linkProgram(Context *context,
    643                                         State *glState,
    644                                         ShaderProgramID vertexShader,
    645                                         ShaderProgramID fragmentShader,
    646                                         const angle::HashMap<GLint, std::string> &attribLocs,
    647                                         ShaderProgramID *programOut)
    648 {
    649    ShaderProgramID program = mShaderPrograms->createProgram(context->getImplementation());
    650 
    651    Program *programObject = getProgram(program);
    652    ANGLE_CHECK(context, programObject, "Missing program object", GL_INVALID_OPERATION);
    653 
    654    *programOut = program;
    655 
    656    programObject->attachShader(getShader(vertexShader));
    657    programObject->attachShader(getShader(fragmentShader));
    658 
    659    for (auto it : attribLocs)
    660    {
    661        GLint index             = it.first;
    662        const std::string &name = it.second;
    663        programObject->bindAttributeLocation(index, name.c_str());
    664    }
    665 
    666    ANGLE_TRY(programObject->link(context));
    667    programObject->resolveLink(context);
    668 
    669    ANGLE_TRY(glState->onProgramExecutableChange(context, programObject));
    670 
    671    if (!programObject->isLinked())
    672    {
    673        GLint infoLogLength = programObject->getExecutable().getInfoLogLength();
    674        std::vector<char> infoLog(infoLogLength, 0);
    675        programObject->getExecutable().getInfoLog(infoLogLength - 1, nullptr, infoLog.data());
    676 
    677        ERR() << "Internal GLES 1 shader link failed. Info log: " << infoLog.data();
    678        ANGLE_CHECK(context, false, "GLES1Renderer program link failed.", GL_INVALID_OPERATION);
    679        return angle::Result::Stop;
    680    }
    681 
    682    programObject->detachShader(context, getShader(vertexShader));
    683    programObject->detachShader(context, getShader(fragmentShader));
    684 
    685    return angle::Result::Continue;
    686 }
    687 
    688 const char *GLES1Renderer::getShaderBool(GLES1StateEnables state)
    689 {
    690    if (mShaderState.mGLES1StateEnabled[state])
    691    {
    692        return "true";
    693    }
    694    else
    695    {
    696        return "false";
    697    }
    698 }
    699 
    700 void GLES1Renderer::addShaderDefine(std::stringstream &outStream,
    701                                    GLES1StateEnables state,
    702                                    const char *enableString)
    703 {
    704    outStream << "\n";
    705    outStream << "#define " << enableString << " " << getShaderBool(state);
    706 }
    707 
    708 void GLES1Renderer::addShaderInt(std::stringstream &outStream, const char *name, int value)
    709 {
    710    outStream << "\n";
    711    outStream << "const int " << name << " = " << value << ";";
    712 }
    713 
    714 void GLES1Renderer::addShaderIntTexArray(std::stringstream &outStream,
    715                                         const char *texString,
    716                                         GLES1ShaderState::IntTexArray &texState)
    717 {
    718    outStream << "\n";
    719    outStream << "const int " << texString << "[kMaxTexUnits] = int[kMaxTexUnits](";
    720    for (int i = 0; i < kTexUnitCount; i++)
    721    {
    722        if (i != 0)
    723        {
    724            outStream << ", ";
    725        }
    726        outStream << texState[i];
    727    }
    728    outStream << ");";
    729 }
    730 
    731 void GLES1Renderer::addShaderBoolTexArray(std::stringstream &outStream,
    732                                          const char *name,
    733                                          GLES1ShaderState::BoolTexArray &value)
    734 {
    735    outStream << std::boolalpha;
    736    outStream << "\n";
    737    outStream << "bool " << name << "[kMaxTexUnits] = bool[kMaxTexUnits](";
    738    for (int i = 0; i < kTexUnitCount; i++)
    739    {
    740        if (i != 0)
    741        {
    742            outStream << ", ";
    743        }
    744        outStream << value[i];
    745    }
    746    outStream << ");";
    747 }
    748 
    749 void GLES1Renderer::addShaderBoolLightArray(std::stringstream &outStream,
    750                                            const char *name,
    751                                            GLES1ShaderState::BoolLightArray &value)
    752 {
    753    outStream << std::boolalpha;
    754    outStream << "\n";
    755    outStream << "bool " << name << "[kMaxLights] = bool[kMaxLights](";
    756    for (int i = 0; i < kLightCount; i++)
    757    {
    758        if (i != 0)
    759        {
    760            outStream << ", ";
    761        }
    762        outStream << value[i];
    763    }
    764    outStream << ");";
    765 }
    766 
    767 void GLES1Renderer::addShaderBoolClipPlaneArray(std::stringstream &outStream,
    768                                                const char *name,
    769                                                GLES1ShaderState::BoolClipPlaneArray &value)
    770 {
    771    outStream << std::boolalpha;
    772    outStream << "\n";
    773    outStream << "bool " << name << "[kMaxClipPlanes] = bool[kMaxClipPlanes](";
    774    for (int i = 0; i < kClipPlaneCount; i++)
    775    {
    776        if (i != 0)
    777        {
    778            outStream << ", ";
    779        }
    780        outStream << value[i];
    781    }
    782    outStream << ");";
    783 }
    784 
    785 void GLES1Renderer::addVertexShaderDefs(std::stringstream &outStream)
    786 {
    787    addShaderDefine(outStream, GLES1StateEnables::Lighting, "enable_lighting");
    788    addShaderDefine(outStream, GLES1StateEnables::ColorMaterial, "enable_color_material");
    789    addShaderDefine(outStream, GLES1StateEnables::DrawTexture, "enable_draw_texture");
    790    addShaderDefine(outStream, GLES1StateEnables::PointRasterization, "point_rasterization");
    791    addShaderDefine(outStream, GLES1StateEnables::RescaleNormal, "enable_rescale_normal");
    792    addShaderDefine(outStream, GLES1StateEnables::Normalize, "enable_normalize");
    793    addShaderDefine(outStream, GLES1StateEnables::LightModelTwoSided, "light_model_two_sided");
    794 
    795    // bool light_enables[kMaxLights] = bool[kMaxLights](...);
    796    addShaderBoolLightArray(outStream, "light_enables", mShaderState.lightEnables);
    797 }
    798 
    799 void GLES1Renderer::addFragmentShaderDefs(std::stringstream &outStream)
    800 {
    801    addShaderDefine(outStream, GLES1StateEnables::Fog, "enable_fog");
    802    addShaderDefine(outStream, GLES1StateEnables::ClipPlanes, "enable_clip_planes");
    803    addShaderDefine(outStream, GLES1StateEnables::DrawTexture, "enable_draw_texture");
    804    addShaderDefine(outStream, GLES1StateEnables::PointRasterization, "point_rasterization");
    805    addShaderDefine(outStream, GLES1StateEnables::PointSprite, "point_sprite_enabled");
    806    addShaderDefine(outStream, GLES1StateEnables::AlphaTest, "enable_alpha_test");
    807    addShaderDefine(outStream, GLES1StateEnables::ShadeModelFlat, "shade_model_flat");
    808 
    809    // bool enable_texture_2d[kMaxTexUnits] = bool[kMaxTexUnits](...);
    810    addShaderBoolTexArray(outStream, "enable_texture_2d", mShaderState.tex2DEnables);
    811 
    812    // bool enable_texture_cube_map[kMaxTexUnits] = bool[kMaxTexUnits](...);
    813    addShaderBoolTexArray(outStream, "enable_texture_cube_map", mShaderState.texCubeEnables);
    814 
    815    // int texture_format[kMaxTexUnits] = int[kMaxTexUnits](...);
    816    addShaderIntTexArray(outStream, "texture_format", mShaderState.tex2DFormats);
    817 
    818    // bool point_sprite_coord_replace[kMaxTexUnits] = bool[kMaxTexUnits](...);
    819    addShaderBoolTexArray(outStream, "point_sprite_coord_replace",
    820                          mShaderState.pointSpriteCoordReplaces);
    821 
    822    // bool clip_plane_enables[kMaxClipPlanes] = bool[kMaxClipPlanes](...);
    823    addShaderBoolClipPlaneArray(outStream, "clip_plane_enables", mShaderState.clipPlaneEnables);
    824 
    825    // int texture_format[kMaxTexUnits] = int[kMaxTexUnits](...);
    826    addShaderIntTexArray(outStream, "texture_env_mode", mShaderState.texEnvModes);
    827 
    828    // int combine_rgb[kMaxTexUnits];
    829    addShaderIntTexArray(outStream, "combine_rgb", mShaderState.texCombineRgbs);
    830 
    831    // int combine_alpha[kMaxTexUnits];
    832    addShaderIntTexArray(outStream, "combine_alpha", mShaderState.texCombineAlphas);
    833 
    834    // int src0_rgb[kMaxTexUnits];
    835    addShaderIntTexArray(outStream, "src0_rgb", mShaderState.texCombineSrc0Rgbs);
    836 
    837    // int src0_alpha[kMaxTexUnits];
    838    addShaderIntTexArray(outStream, "src0_alpha", mShaderState.texCombineSrc0Alphas);
    839 
    840    // int src1_rgb[kMaxTexUnits];
    841    addShaderIntTexArray(outStream, "src1_rgb", mShaderState.texCombineSrc1Rgbs);
    842 
    843    // int src1_alpha[kMaxTexUnits];
    844    addShaderIntTexArray(outStream, "src1_alpha", mShaderState.texCombineSrc1Alphas);
    845 
    846    // int src2_rgb[kMaxTexUnits];
    847    addShaderIntTexArray(outStream, "src2_rgb", mShaderState.texCombineSrc2Rgbs);
    848 
    849    // int src2_alpha[kMaxTexUnits];
    850    addShaderIntTexArray(outStream, "src2_alpha", mShaderState.texCombineSrc2Alphas);
    851 
    852    // int op0_rgb[kMaxTexUnits];
    853    addShaderIntTexArray(outStream, "op0_rgb", mShaderState.texCombineOp0Rgbs);
    854 
    855    // int op0_alpha[kMaxTexUnits];
    856    addShaderIntTexArray(outStream, "op0_alpha", mShaderState.texCombineOp0Alphas);
    857 
    858    // int op1_rgb[kMaxTexUnits];
    859    addShaderIntTexArray(outStream, "op1_rgb", mShaderState.texCombineOp1Rgbs);
    860 
    861    // int op1_alpha[kMaxTexUnits];
    862    addShaderIntTexArray(outStream, "op1_alpha", mShaderState.texCombineOp1Alphas);
    863 
    864    // int op2_rgb[kMaxTexUnits];
    865    addShaderIntTexArray(outStream, "op2_rgb", mShaderState.texCombineOp2Rgbs);
    866 
    867    // int op2_alpha[kMaxTexUnits];
    868    addShaderIntTexArray(outStream, "op2_alpha", mShaderState.texCombineOp2Alphas);
    869 
    870    // int alpha_func;
    871    addShaderInt(outStream, "alpha_func", ToGLenum(mShaderState.alphaTestFunc));
    872 
    873    // int fog_mode;
    874    addShaderInt(outStream, "fog_mode", ToGLenum(mShaderState.fogMode));
    875 }
    876 
    877 angle::Result GLES1Renderer::initializeRendererProgram(Context *context, State *glState)
    878 {
    879    // See if we have the shader for this combination of states
    880    if (mUberShaderState.find(mShaderState) != mUberShaderState.end())
    881    {
    882        Program *programObject = getProgram(getUberShaderState().programState.program);
    883 
    884        // If this is different than the current program, we need to sync everything
    885        // TODO: This could be optimized to only dirty state that differs between the two programs
    886        if (glState->getProgram()->id() != programObject->id())
    887        {
    888            glState->gles1().setAllDirty();
    889        }
    890 
    891        ANGLE_TRY(glState->setProgram(context, programObject));
    892        return angle::Result::Continue;
    893    }
    894 
    895    if (!mRendererProgramInitialized)
    896    {
    897        mShaderPrograms = new ShaderProgramManager();
    898    }
    899 
    900    // If we get here, we don't have a shader for this state, need to create it
    901    GLES1ProgramState &programState = mUberShaderState[mShaderState].programState;
    902 
    903    ShaderProgramID vertexShader;
    904    ShaderProgramID fragmentShader;
    905 
    906    std::stringstream GLES1DrawVShaderStateDefs;
    907    addVertexShaderDefs(GLES1DrawVShaderStateDefs);
    908 
    909    std::stringstream vertexStream;
    910    vertexStream << kGLES1DrawVShaderHeader;
    911    vertexStream << GLES1DrawVShaderStateDefs.str();
    912    vertexStream << kGLES1DrawVShader;
    913 
    914    ANGLE_TRY(
    915        compileShader(context, ShaderType::Vertex, vertexStream.str().c_str(), &vertexShader));
    916 
    917    std::stringstream GLES1DrawFShaderStateDefs;
    918    addFragmentShaderDefs(GLES1DrawFShaderStateDefs);
    919 
    920    std::stringstream fragmentStream;
    921    fragmentStream << kGLES1DrawFShaderVersion;
    922    if (mShaderState.mGLES1StateEnabled[GLES1StateEnables::LogicOpThroughFramebufferFetch])
    923    {
    924        if (context->getExtensions().shaderFramebufferFetchEXT)
    925        {
    926            fragmentStream << "#extension GL_EXT_shader_framebuffer_fetch : require\n";
    927        }
    928        else
    929        {
    930            fragmentStream << "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n";
    931        }
    932    }
    933    fragmentStream << kGLES1DrawFShaderHeader;
    934    fragmentStream << GLES1DrawFShaderStateDefs.str();
    935    fragmentStream << kGLES1DrawFShaderUniformDefs;
    936    if (mShaderState.mGLES1StateEnabled[GLES1StateEnables::LogicOpThroughFramebufferFetch])
    937    {
    938        if (context->getExtensions().shaderFramebufferFetchEXT)
    939        {
    940            fragmentStream << kGLES1DrawFShaderFramebufferFetchOutputDef;
    941        }
    942        else
    943        {
    944            fragmentStream << kGLES1DrawFShaderFramebufferFetchNonCoherentOutputDef;
    945        }
    946        fragmentStream << kGLES1DrawFShaderLogicOpFramebufferFetchEnabled;
    947    }
    948    else
    949    {
    950        fragmentStream << kGLES1DrawFShaderOutputDef;
    951        fragmentStream << kGLES1DrawFShaderLogicOpFramebufferFetchDisabled;
    952    }
    953    fragmentStream << kGLES1DrawFShaderFunctions;
    954    fragmentStream << kGLES1DrawFShaderMultitexturing;
    955    fragmentStream << kGLES1DrawFShaderMain;
    956 
    957    ANGLE_TRY(compileShader(context, ShaderType::Fragment, fragmentStream.str().c_str(),
    958                            &fragmentShader));
    959 
    960    angle::HashMap<GLint, std::string> attribLocs;
    961 
    962    attribLocs[(GLint)kVertexAttribIndex]    = "pos";
    963    attribLocs[(GLint)kNormalAttribIndex]    = "normal";
    964    attribLocs[(GLint)kColorAttribIndex]     = "color";
    965    attribLocs[(GLint)kPointSizeAttribIndex] = "pointsize";
    966 
    967    for (int i = 0; i < kTexUnitCount; i++)
    968    {
    969        std::stringstream ss;
    970        ss << "texcoord" << i;
    971        attribLocs[kTextureCoordAttribIndexBase + i] = ss.str();
    972    }
    973 
    974    ANGLE_TRY(linkProgram(context, glState, vertexShader, fragmentShader, attribLocs,
    975                          &programState.program));
    976 
    977    mShaderPrograms->deleteShader(context, vertexShader);
    978    mShaderPrograms->deleteShader(context, fragmentShader);
    979 
    980    Program *programObject = getProgram(programState.program);
    981 
    982    programState.projMatrixLoc      = programObject->getUniformLocation("projection");
    983    programState.modelviewMatrixLoc = programObject->getUniformLocation("modelview");
    984    programState.textureMatrixLoc   = programObject->getUniformLocation("texture_matrix");
    985    programState.modelviewInvTrLoc  = programObject->getUniformLocation("modelview_invtr");
    986 
    987    for (int i = 0; i < kTexUnitCount; i++)
    988    {
    989        std::stringstream ss2d;
    990        std::stringstream sscube;
    991 
    992        ss2d << "tex_sampler" << i;
    993        sscube << "tex_cube_sampler" << i;
    994 
    995        programState.tex2DSamplerLocs[i] = programObject->getUniformLocation(ss2d.str().c_str());
    996        programState.texCubeSamplerLocs[i] =
    997            programObject->getUniformLocation(sscube.str().c_str());
    998    }
    999 
   1000    programState.textureEnvColorLoc = programObject->getUniformLocation("texture_env_color");
   1001    programState.rgbScaleLoc        = programObject->getUniformLocation("texture_env_rgb_scale");
   1002    programState.alphaScaleLoc      = programObject->getUniformLocation("texture_env_alpha_scale");
   1003 
   1004    programState.alphaTestRefLoc = programObject->getUniformLocation("alpha_test_ref");
   1005 
   1006    programState.materialAmbientLoc  = programObject->getUniformLocation("material_ambient");
   1007    programState.materialDiffuseLoc  = programObject->getUniformLocation("material_diffuse");
   1008    programState.materialSpecularLoc = programObject->getUniformLocation("material_specular");
   1009    programState.materialEmissiveLoc = programObject->getUniformLocation("material_emissive");
   1010    programState.materialSpecularExponentLoc =
   1011        programObject->getUniformLocation("material_specular_exponent");
   1012 
   1013    programState.lightModelSceneAmbientLoc =
   1014        programObject->getUniformLocation("light_model_scene_ambient");
   1015 
   1016    programState.lightAmbientsLoc   = programObject->getUniformLocation("light_ambients");
   1017    programState.lightDiffusesLoc   = programObject->getUniformLocation("light_diffuses");
   1018    programState.lightSpecularsLoc  = programObject->getUniformLocation("light_speculars");
   1019    programState.lightPositionsLoc  = programObject->getUniformLocation("light_positions");
   1020    programState.lightDirectionsLoc = programObject->getUniformLocation("light_directions");
   1021    programState.lightSpotlightExponentsLoc =
   1022        programObject->getUniformLocation("light_spotlight_exponents");
   1023    programState.lightSpotlightCutoffAnglesLoc =
   1024        programObject->getUniformLocation("light_spotlight_cutoff_angles");
   1025    programState.lightAttenuationConstsLoc =
   1026        programObject->getUniformLocation("light_attenuation_consts");
   1027    programState.lightAttenuationLinearsLoc =
   1028        programObject->getUniformLocation("light_attenuation_linears");
   1029    programState.lightAttenuationQuadraticsLoc =
   1030        programObject->getUniformLocation("light_attenuation_quadratics");
   1031 
   1032    programState.fogDensityLoc = programObject->getUniformLocation("fog_density");
   1033    programState.fogStartLoc   = programObject->getUniformLocation("fog_start");
   1034    programState.fogEndLoc     = programObject->getUniformLocation("fog_end");
   1035    programState.fogColorLoc   = programObject->getUniformLocation("fog_color");
   1036 
   1037    programState.clipPlanesLoc = programObject->getUniformLocation("clip_planes");
   1038 
   1039    programState.logicOpLoc = programObject->getUniformLocation("logic_op");
   1040 
   1041    programState.pointSizeMinLoc = programObject->getUniformLocation("point_size_min");
   1042    programState.pointSizeMaxLoc = programObject->getUniformLocation("point_size_max");
   1043    programState.pointDistanceAttenuationLoc =
   1044        programObject->getUniformLocation("point_distance_attenuation");
   1045 
   1046    programState.drawTextureCoordsLoc = programObject->getUniformLocation("draw_texture_coords");
   1047    programState.drawTextureDimsLoc   = programObject->getUniformLocation("draw_texture_dims");
   1048    programState.drawTextureNormalizedCropRectLoc =
   1049        programObject->getUniformLocation("draw_texture_normalized_crop_rect");
   1050 
   1051    ANGLE_TRY(glState->setProgram(context, programObject));
   1052 
   1053    for (int i = 0; i < kTexUnitCount; i++)
   1054    {
   1055        setUniform1i(context, programObject, programState.tex2DSamplerLocs[i], i);
   1056        setUniform1i(context, programObject, programState.texCubeSamplerLocs[i], i + kTexUnitCount);
   1057    }
   1058    glState->setObjectDirty(GL_PROGRAM);
   1059 
   1060    // We just created a new program, we need to sync everything
   1061    glState->gles1().setAllDirty();
   1062 
   1063    mRendererProgramInitialized = true;
   1064    return angle::Result::Continue;
   1065 }
   1066 
   1067 void GLES1Renderer::setUniform1i(Context *context,
   1068                                 Program *programObject,
   1069                                 UniformLocation location,
   1070                                 GLint value)
   1071 {
   1072    if (location.value == -1)
   1073        return;
   1074    programObject->setUniform1iv(context, location, 1, &value);
   1075 }
   1076 
   1077 void GLES1Renderer::setUniform1ui(Program *programObject, UniformLocation location, GLuint value)
   1078 {
   1079    if (location.value == -1)
   1080        return;
   1081    programObject->setUniform1uiv(location, 1, &value);
   1082 }
   1083 
   1084 void GLES1Renderer::setUniform1iv(Context *context,
   1085                                  Program *programObject,
   1086                                  UniformLocation location,
   1087                                  GLint count,
   1088                                  const GLint *value)
   1089 {
   1090    if (location.value == -1)
   1091        return;
   1092    programObject->setUniform1iv(context, location, count, value);
   1093 }
   1094 
   1095 void GLES1Renderer::setUniformMatrix4fv(Program *programObject,
   1096                                        UniformLocation location,
   1097                                        GLint count,
   1098                                        GLboolean transpose,
   1099                                        const GLfloat *value)
   1100 {
   1101    if (location.value == -1)
   1102        return;
   1103    programObject->setUniformMatrix4fv(location, count, transpose, value);
   1104 }
   1105 
   1106 void GLES1Renderer::setUniform4fv(Program *programObject,
   1107                                  UniformLocation location,
   1108                                  GLint count,
   1109                                  const GLfloat *value)
   1110 {
   1111    if (location.value == -1)
   1112        return;
   1113    programObject->setUniform4fv(location, count, value);
   1114 }
   1115 
   1116 void GLES1Renderer::setUniform3fv(Program *programObject,
   1117                                  UniformLocation location,
   1118                                  GLint count,
   1119                                  const GLfloat *value)
   1120 {
   1121    if (location.value == -1)
   1122        return;
   1123    programObject->setUniform3fv(location, count, value);
   1124 }
   1125 
   1126 void GLES1Renderer::setUniform2fv(Program *programObject,
   1127                                  UniformLocation location,
   1128                                  GLint count,
   1129                                  const GLfloat *value)
   1130 {
   1131    if (location.value == -1)
   1132        return;
   1133    programObject->setUniform2fv(location, count, value);
   1134 }
   1135 
   1136 void GLES1Renderer::setUniform1f(Program *programObject, UniformLocation location, GLfloat value)
   1137 {
   1138    if (location.value == -1)
   1139        return;
   1140    programObject->setUniform1fv(location, 1, &value);
   1141 }
   1142 
   1143 void GLES1Renderer::setUniform1fv(Program *programObject,
   1144                                  UniformLocation location,
   1145                                  GLint count,
   1146                                  const GLfloat *value)
   1147 {
   1148    if (location.value == -1)
   1149        return;
   1150    programObject->setUniform1fv(location, count, value);
   1151 }
   1152 
   1153 void GLES1Renderer::setAttributesEnabled(Context *context, State *glState, AttributesMask mask)
   1154 {
   1155    GLES1State &gles1 = glState->gles1();
   1156 
   1157    ClientVertexArrayType nonTexcoordArrays[] = {
   1158        ClientVertexArrayType::Vertex,
   1159        ClientVertexArrayType::Normal,
   1160        ClientVertexArrayType::Color,
   1161        ClientVertexArrayType::PointSize,
   1162    };
   1163 
   1164    for (const ClientVertexArrayType attrib : nonTexcoordArrays)
   1165    {
   1166        int index = VertexArrayIndex(attrib, glState->gles1());
   1167 
   1168        if (mask.test(index))
   1169        {
   1170            gles1.setClientStateEnabled(attrib, true);
   1171            context->enableVertexAttribArray(index);
   1172        }
   1173        else
   1174        {
   1175            gles1.setClientStateEnabled(attrib, false);
   1176            context->disableVertexAttribArray(index);
   1177        }
   1178    }
   1179 
   1180    for (unsigned int i = 0; i < kTexUnitCount; i++)
   1181    {
   1182        int index = TexCoordArrayIndex(i);
   1183 
   1184        if (mask.test(index))
   1185        {
   1186            gles1.setTexCoordArrayEnabled(i, true);
   1187            context->enableVertexAttribArray(index);
   1188        }
   1189        else
   1190        {
   1191            gles1.setTexCoordArrayEnabled(i, false);
   1192            context->disableVertexAttribArray(index);
   1193        }
   1194    }
   1195 }
   1196 
   1197 }  // namespace gl