| // | |
| // Copyright 2018 The ANGLE Project Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // | |
| // GLES1Renderer.cpp: Implements the GLES1Renderer renderer. | |
| #include "libANGLE/GLES1Renderer.h" | |
| #include <string.h> | |
| #include <iterator> | |
| #include <sstream> | |
| #include <vector> | |
| #include "libANGLE/Context.h" | |
| #include "libANGLE/Program.h" | |
| #include "libANGLE/ResourceManager.h" | |
| #include "libANGLE/Shader.h" | |
| #include "libANGLE/State.h" | |
| #include "libANGLE/renderer/ContextImpl.h" | |
| namespace | |
| { | |
| #include "libANGLE/GLES1Shaders.inc" | |
| } // anonymous namespace | |
| namespace gl | |
| { | |
| GLES1Renderer::GLES1Renderer() : mRendererProgramInitialized(false) | |
| { | |
| } | |
| void GLES1Renderer::onDestroy(Context *context, State *state) | |
| { | |
| if (mRendererProgramInitialized) | |
| { | |
| state->setProgram(context, 0); | |
| mShaderPrograms->deleteProgram(context, mProgramState.program); | |
| mShaderPrograms->release(context); | |
| mShaderPrograms = nullptr; | |
| mRendererProgramInitialized = false; | |
| } | |
| } | |
| GLES1Renderer::~GLES1Renderer() = default; | |
| Error GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State *glState) | |
| { | |
| ANGLE_TRY(initializeRendererProgram(context, glState)); | |
| const GLES1State &gles1State = glState->gles1(); | |
| Program *programObject = getProgram(mProgramState.program); | |
| GLES1UniformBuffers &uniformBuffers = mUniformBuffers; | |
| if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Normal)) | |
| { | |
| const angle::Vector3 normal = gles1State.getCurrentNormal(); | |
| context->vertexAttrib3f(kNormalAttribIndex, normal.x(), normal.y(), normal.z()); | |
| } | |
| if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Color)) | |
| { | |
| const ColorF color = gles1State.getCurrentColor(); | |
| context->vertexAttrib4f(kColorAttribIndex, color.red, color.green, color.blue, color.alpha); | |
| } | |
| if (!gles1State.isClientStateEnabled(ClientVertexArrayType::PointSize)) | |
| { | |
| GLfloat pointSize = gles1State.mPointParameters.pointSize; | |
| context->vertexAttrib1f(kPointSizeAttribIndex, pointSize); | |
| } | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| if (!gles1State.mTexCoordArrayEnabled[i]) | |
| { | |
| const TextureCoordF texcoord = gles1State.getCurrentTextureCoords(i); | |
| context->vertexAttrib4f(kTextureCoordAttribIndexBase + i, texcoord.s, texcoord.t, | |
| texcoord.r, texcoord.q); | |
| } | |
| } | |
| // Matrices | |
| { | |
| angle::Mat4 proj = gles1State.mProjectionMatrices.back(); | |
| setUniformMatrix4fv(programObject, mProgramState.projMatrixLoc, 1, GL_FALSE, proj.data()); | |
| angle::Mat4 modelview = gles1State.mModelviewMatrices.back(); | |
| setUniformMatrix4fv(programObject, mProgramState.modelviewMatrixLoc, 1, GL_FALSE, | |
| modelview.data()); | |
| angle::Mat4 modelviewInvTr = modelview.transpose().inverse(); | |
| setUniformMatrix4fv(programObject, mProgramState.modelviewInvTrLoc, 1, GL_FALSE, | |
| modelviewInvTr.data()); | |
| Mat4Uniform *textureMatrixBuffer = uniformBuffers.textureMatrices.data(); | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| angle::Mat4 textureMatrix = gles1State.mTextureMatrices[i].back(); | |
| memcpy(textureMatrixBuffer + i, textureMatrix.data(), sizeof(Mat4Uniform)); | |
| } | |
| setUniformMatrix4fv(programObject, mProgramState.textureMatrixLoc, kTexUnitCount, GL_FALSE, | |
| reinterpret_cast<float *>(uniformBuffers.textureMatrices.data())); | |
| } | |
| // Texturing | |
| { | |
| std::array<GLint, kTexUnitCount> &tex2DEnables = uniformBuffers.tex2DEnables; | |
| std::array<GLint, kTexUnitCount> &texCubeEnables = uniformBuffers.texCubeEnables; | |
| std::vector<int> tex2DFormats = {GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA}; | |
| Vec4Uniform *cropRectBuffer = uniformBuffers.texCropRects.data(); | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| // GL_OES_cube_map allows only one of TEXTURE_2D / TEXTURE_CUBE_MAP | |
| // to be enabled per unit, thankfully. From the extension text: | |
| // | |
| // -- Section 3.8.10 "Texture Application" | |
| // | |
| // Replace the beginning sentences of the first paragraph (page 138) | |
| // with: | |
| // | |
| // "Texturing is enabled or disabled using the generic Enable | |
| // and Disable commands, respectively, with the symbolic constants | |
| // TEXTURE_2D or TEXTURE_CUBE_MAP_OES to enable the two-dimensional or cube | |
| // map texturing respectively. If the cube map texture and the two- | |
| // dimensional texture are enabled, then cube map texturing is used. If | |
| // texturing is disabled, a rasterized fragment is passed on unaltered to the | |
| // next stage of the GL (although its texture coordinates may be discarded). | |
| // Otherwise, a texture value is found according to the parameter values of | |
| // the currently bound texture image of the appropriate dimensionality. | |
| texCubeEnables[i] = gles1State.isTextureTargetEnabled(i, TextureType::CubeMap); | |
| tex2DEnables[i] = | |
| !texCubeEnables[i] && (gles1State.isTextureTargetEnabled(i, TextureType::_2D)); | |
| Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D); | |
| if (curr2DTexture) | |
| { | |
| tex2DFormats[i] = gl::GetUnsizedFormat( | |
| curr2DTexture->getFormat(TextureTarget::_2D, 0).info->internalFormat); | |
| const gl::Rectangle &cropRect = curr2DTexture->getCrop(); | |
| GLfloat textureWidth = | |
| static_cast<GLfloat>(curr2DTexture->getWidth(TextureTarget::_2D, 0)); | |
| GLfloat textureHeight = | |
| static_cast<GLfloat>(curr2DTexture->getHeight(TextureTarget::_2D, 0)); | |
| if (textureWidth > 0.0f && textureHeight > 0.0f) | |
| { | |
| cropRectBuffer[i][0] = cropRect.x / textureWidth; | |
| cropRectBuffer[i][1] = cropRect.y / textureHeight; | |
| cropRectBuffer[i][2] = cropRect.width / textureWidth; | |
| cropRectBuffer[i][3] = cropRect.height / textureHeight; | |
| } | |
| } | |
| } | |
| setUniform1iv(programObject, mProgramState.enableTexture2DLoc, kTexUnitCount, | |
| tex2DEnables.data()); | |
| setUniform1iv(programObject, mProgramState.enableTextureCubeMapLoc, kTexUnitCount, | |
| texCubeEnables.data()); | |
| setUniform1iv(programObject, mProgramState.textureFormatLoc, kTexUnitCount, | |
| tex2DFormats.data()); | |
| setUniform4fv(programObject, mProgramState.drawTextureNormalizedCropRectLoc, kTexUnitCount, | |
| reinterpret_cast<GLfloat *>(cropRectBuffer)); | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| const auto &env = gles1State.textureEnvironment(i); | |
| uniformBuffers.texEnvModes[i] = ToGLenum(env.mode); | |
| uniformBuffers.texCombineRgbs[i] = ToGLenum(env.combineRgb); | |
| uniformBuffers.texCombineAlphas[i] = ToGLenum(env.combineAlpha); | |
| uniformBuffers.texCombineSrc0Rgbs[i] = ToGLenum(env.src0Rgb); | |
| uniformBuffers.texCombineSrc0Alphas[i] = ToGLenum(env.src0Alpha); | |
| uniformBuffers.texCombineSrc1Rgbs[i] = ToGLenum(env.src1Rgb); | |
| uniformBuffers.texCombineSrc1Alphas[i] = ToGLenum(env.src1Alpha); | |
| uniformBuffers.texCombineSrc2Rgbs[i] = ToGLenum(env.src2Rgb); | |
| uniformBuffers.texCombineSrc2Alphas[i] = ToGLenum(env.src2Alpha); | |
| uniformBuffers.texCombineOp0Rgbs[i] = ToGLenum(env.op0Rgb); | |
| uniformBuffers.texCombineOp0Alphas[i] = ToGLenum(env.op0Alpha); | |
| uniformBuffers.texCombineOp1Rgbs[i] = ToGLenum(env.op1Rgb); | |
| uniformBuffers.texCombineOp1Alphas[i] = ToGLenum(env.op1Alpha); | |
| uniformBuffers.texCombineOp2Rgbs[i] = ToGLenum(env.op2Rgb); | |
| uniformBuffers.texCombineOp2Alphas[i] = ToGLenum(env.op2Alpha); | |
| uniformBuffers.texEnvColors[i][0] = env.color.red; | |
| uniformBuffers.texEnvColors[i][1] = env.color.green; | |
| uniformBuffers.texEnvColors[i][2] = env.color.blue; | |
| uniformBuffers.texEnvColors[i][3] = env.color.alpha; | |
| uniformBuffers.texEnvRgbScales[i] = env.rgbScale; | |
| uniformBuffers.texEnvAlphaScales[i] = env.alphaScale; | |
| uniformBuffers.pointSpriteCoordReplaces[i] = env.pointSpriteCoordReplace; | |
| } | |
| setUniform1iv(programObject, mProgramState.textureEnvModeLoc, kTexUnitCount, | |
| uniformBuffers.texEnvModes.data()); | |
| setUniform1iv(programObject, mProgramState.combineRgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineRgbs.data()); | |
| setUniform1iv(programObject, mProgramState.combineAlphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineAlphas.data()); | |
| setUniform1iv(programObject, mProgramState.src0rgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineSrc0Rgbs.data()); | |
| setUniform1iv(programObject, mProgramState.src0alphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineSrc0Alphas.data()); | |
| setUniform1iv(programObject, mProgramState.src1rgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineSrc1Rgbs.data()); | |
| setUniform1iv(programObject, mProgramState.src1alphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineSrc1Alphas.data()); | |
| setUniform1iv(programObject, mProgramState.src2rgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineSrc2Rgbs.data()); | |
| setUniform1iv(programObject, mProgramState.src2alphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineSrc2Alphas.data()); | |
| setUniform1iv(programObject, mProgramState.op0rgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineOp0Rgbs.data()); | |
| setUniform1iv(programObject, mProgramState.op0alphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineOp0Alphas.data()); | |
| setUniform1iv(programObject, mProgramState.op1rgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineOp1Rgbs.data()); | |
| setUniform1iv(programObject, mProgramState.op1alphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineOp1Alphas.data()); | |
| setUniform1iv(programObject, mProgramState.op2rgbLoc, kTexUnitCount, | |
| uniformBuffers.texCombineOp2Rgbs.data()); | |
| setUniform1iv(programObject, mProgramState.op2alphaLoc, kTexUnitCount, | |
| uniformBuffers.texCombineOp2Alphas.data()); | |
| setUniform4fv(programObject, mProgramState.textureEnvColorLoc, kTexUnitCount, | |
| reinterpret_cast<float *>(uniformBuffers.texEnvColors.data())); | |
| setUniform1fv(programObject, mProgramState.rgbScaleLoc, kTexUnitCount, | |
| uniformBuffers.texEnvRgbScales.data()); | |
| setUniform1fv(programObject, mProgramState.alphaScaleLoc, kTexUnitCount, | |
| uniformBuffers.texEnvAlphaScales.data()); | |
| setUniform1iv(programObject, mProgramState.pointSpriteCoordReplaceLoc, kTexUnitCount, | |
| uniformBuffers.pointSpriteCoordReplaces.data()); | |
| } | |
| // Alpha test | |
| { | |
| setUniform1i(programObject, mProgramState.enableAlphaTestLoc, | |
| glState->getEnableFeature(GL_ALPHA_TEST)); | |
| setUniform1i(programObject, mProgramState.alphaFuncLoc, | |
| ToGLenum(gles1State.mAlphaTestFunc)); | |
| setUniform1f(programObject, mProgramState.alphaTestRefLoc, gles1State.mAlphaTestRef); | |
| } | |
| // Shading, materials, and lighting | |
| { | |
| setUniform1i(programObject, mProgramState.shadeModelFlatLoc, | |
| gles1State.mShadeModel == ShadingModel::Flat); | |
| setUniform1i(programObject, mProgramState.enableLightingLoc, | |
| glState->getEnableFeature(GL_LIGHTING)); | |
| setUniform1i(programObject, mProgramState.enableRescaleNormalLoc, | |
| glState->getEnableFeature(GL_RESCALE_NORMAL)); | |
| setUniform1i(programObject, mProgramState.enableNormalizeLoc, | |
| glState->getEnableFeature(GL_NORMALIZE)); | |
| setUniform1i(programObject, mProgramState.enableColorMaterialLoc, | |
| glState->getEnableFeature(GL_COLOR_MATERIAL)); | |
| const auto &material = gles1State.mMaterial; | |
| setUniform4fv(programObject, mProgramState.materialAmbientLoc, 1, material.ambient.data()); | |
| setUniform4fv(programObject, mProgramState.materialDiffuseLoc, 1, material.diffuse.data()); | |
| setUniform4fv(programObject, mProgramState.materialSpecularLoc, 1, | |
| material.specular.data()); | |
| setUniform4fv(programObject, mProgramState.materialEmissiveLoc, 1, | |
| material.emissive.data()); | |
| setUniform1f(programObject, mProgramState.materialSpecularExponentLoc, | |
| material.specularExponent); | |
| const auto &lightModel = gles1State.mLightModel; | |
| setUniform4fv(programObject, mProgramState.lightModelSceneAmbientLoc, 1, | |
| lightModel.color.data()); | |
| // TODO (lfy@google.com): Implement two-sided lighting model | |
| // gl->uniform1i(mProgramState.lightModelTwoSidedLoc, lightModel.twoSided); | |
| for (int i = 0; i < kLightCount; i++) | |
| { | |
| const auto &light = gles1State.mLights[i]; | |
| uniformBuffers.lightEnables[i] = light.enabled; | |
| memcpy(uniformBuffers.lightAmbients.data() + i, light.ambient.data(), | |
| sizeof(Vec4Uniform)); | |
| memcpy(uniformBuffers.lightDiffuses.data() + i, light.diffuse.data(), | |
| sizeof(Vec4Uniform)); | |
| memcpy(uniformBuffers.lightSpeculars.data() + i, light.specular.data(), | |
| sizeof(Vec4Uniform)); | |
| memcpy(uniformBuffers.lightPositions.data() + i, light.position.data(), | |
| sizeof(Vec4Uniform)); | |
| memcpy(uniformBuffers.lightDirections.data() + i, light.direction.data(), | |
| sizeof(Vec3Uniform)); | |
| uniformBuffers.spotlightExponents[i] = light.spotlightExponent; | |
| uniformBuffers.spotlightCutoffAngles[i] = light.spotlightCutoffAngle; | |
| uniformBuffers.attenuationConsts[i] = light.attenuationConst; | |
| uniformBuffers.attenuationLinears[i] = light.attenuationLinear; | |
| uniformBuffers.attenuationQuadratics[i] = light.attenuationQuadratic; | |
| } | |
| setUniform1iv(programObject, mProgramState.lightEnablesLoc, kLightCount, | |
| uniformBuffers.lightEnables.data()); | |
| setUniform4fv(programObject, mProgramState.lightAmbientsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.lightAmbients.data())); | |
| setUniform4fv(programObject, mProgramState.lightDiffusesLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.lightDiffuses.data())); | |
| setUniform4fv(programObject, mProgramState.lightSpecularsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.lightSpeculars.data())); | |
| setUniform4fv(programObject, mProgramState.lightPositionsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.lightPositions.data())); | |
| setUniform3fv(programObject, mProgramState.lightDirectionsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.lightDirections.data())); | |
| setUniform1fv(programObject, mProgramState.lightSpotlightExponentsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.spotlightExponents.data())); | |
| setUniform1fv(programObject, mProgramState.lightSpotlightCutoffAnglesLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.spotlightCutoffAngles.data())); | |
| setUniform1fv(programObject, mProgramState.lightAttenuationConstsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.attenuationConsts.data())); | |
| setUniform1fv(programObject, mProgramState.lightAttenuationLinearsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.attenuationLinears.data())); | |
| setUniform1fv(programObject, mProgramState.lightAttenuationQuadraticsLoc, kLightCount, | |
| reinterpret_cast<float *>(uniformBuffers.attenuationQuadratics.data())); | |
| } | |
| // Fog | |
| { | |
| const FogParameters &fog = gles1State.fogParameters(); | |
| setUniform1i(programObject, mProgramState.fogEnableLoc, glState->getEnableFeature(GL_FOG)); | |
| setUniform1i(programObject, mProgramState.fogModeLoc, ToGLenum(fog.mode)); | |
| setUniform1f(programObject, mProgramState.fogDensityLoc, fog.density); | |
| setUniform1f(programObject, mProgramState.fogStartLoc, fog.start); | |
| setUniform1f(programObject, mProgramState.fogEndLoc, fog.end); | |
| setUniform4fv(programObject, mProgramState.fogColorLoc, 1, fog.color.data()); | |
| } | |
| // Clip planes | |
| { | |
| bool enableClipPlanes = false; | |
| for (int i = 0; i < kClipPlaneCount; i++) | |
| { | |
| uniformBuffers.clipPlaneEnables[i] = glState->getEnableFeature(GL_CLIP_PLANE0 + i); | |
| enableClipPlanes = enableClipPlanes || uniformBuffers.clipPlaneEnables[i]; | |
| gles1State.getClipPlane( | |
| i, reinterpret_cast<float *>(uniformBuffers.clipPlanes.data() + i)); | |
| } | |
| setUniform1i(programObject, mProgramState.enableClipPlanesLoc, enableClipPlanes); | |
| setUniform1iv(programObject, mProgramState.clipPlaneEnablesLoc, kClipPlaneCount, | |
| uniformBuffers.clipPlaneEnables.data()); | |
| setUniform4fv(programObject, mProgramState.clipPlanesLoc, kClipPlaneCount, | |
| reinterpret_cast<float *>(uniformBuffers.clipPlanes.data())); | |
| } | |
| // Point rasterization | |
| { | |
| const PointParameters &pointParams = gles1State.mPointParameters; | |
| setUniform1i(programObject, mProgramState.pointRasterizationLoc, | |
| mode == PrimitiveMode::Points); | |
| setUniform1i(programObject, mProgramState.pointSpriteEnabledLoc, | |
| glState->getEnableFeature(GL_POINT_SPRITE_OES)); | |
| setUniform1f(programObject, mProgramState.pointSizeMinLoc, pointParams.pointSizeMin); | |
| setUniform1f(programObject, mProgramState.pointSizeMaxLoc, pointParams.pointSizeMax); | |
| setUniform3fv(programObject, mProgramState.pointDistanceAttenuationLoc, 1, | |
| pointParams.pointDistanceAttenuation.data()); | |
| } | |
| // Draw texture | |
| { | |
| setUniform1i(programObject, mProgramState.enableDrawTextureLoc, | |
| mDrawTextureEnabled ? 1 : 0); | |
| setUniform4fv(programObject, mProgramState.drawTextureCoordsLoc, 1, mDrawTextureCoords); | |
| setUniform2fv(programObject, mProgramState.drawTextureDimsLoc, 1, mDrawTextureDims); | |
| } | |
| // None of those are changes in sampler, so there is no need to set the GL_PROGRAM dirty. | |
| // Otherwise, put the dirtying here. | |
| return NoError(); | |
| } | |
| // static | |
| int GLES1Renderer::VertexArrayIndex(ClientVertexArrayType type, const GLES1State &gles1) | |
| { | |
| switch (type) | |
| { | |
| case ClientVertexArrayType::Vertex: | |
| return kVertexAttribIndex; | |
| case ClientVertexArrayType::Normal: | |
| return kNormalAttribIndex; | |
| case ClientVertexArrayType::Color: | |
| return kColorAttribIndex; | |
| case ClientVertexArrayType::PointSize: | |
| return kPointSizeAttribIndex; | |
| case ClientVertexArrayType::TextureCoord: | |
| return kTextureCoordAttribIndexBase + gles1.getClientTextureUnit(); | |
| default: | |
| UNREACHABLE(); | |
| return 0; | |
| } | |
| } | |
| // static | |
| int GLES1Renderer::TexCoordArrayIndex(unsigned int unit) | |
| { | |
| return kTextureCoordAttribIndexBase + unit; | |
| } | |
| void GLES1Renderer::drawTexture(Context *context, | |
| State *glState, | |
| float x, | |
| float y, | |
| float z, | |
| float width, | |
| float height) | |
| { | |
| // get viewport | |
| const gl::Rectangle &viewport = glState->getViewport(); | |
| // Translate from viewport to NDC for feeding the shader. | |
| // Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1]) | |
| float xNdc = scaleScreenCoordinateToNdc(x, static_cast<GLfloat>(viewport.width)); | |
| float yNdc = scaleScreenCoordinateToNdc(y, static_cast<GLfloat>(viewport.height)); | |
| float wNdc = scaleScreenDimensionToNdc(width, static_cast<GLfloat>(viewport.width)); | |
| float hNdc = scaleScreenDimensionToNdc(height, static_cast<GLfloat>(viewport.height)); | |
| float zNdc = 2.0f * clamp(z, 0.0f, 1.0f) - 1.0f; | |
| mDrawTextureCoords[0] = xNdc; | |
| mDrawTextureCoords[1] = yNdc; | |
| mDrawTextureCoords[2] = zNdc; | |
| mDrawTextureDims[0] = wNdc; | |
| mDrawTextureDims[1] = hNdc; | |
| mDrawTextureEnabled = true; | |
| AttributesMask prevAttributesMask = glState->gles1().getVertexArraysAttributeMask(); | |
| setAttributesEnabled(context, glState, AttributesMask()); | |
| context->gatherParams<EntryPoint::DrawArrays>(PrimitiveMode::Triangles, 0, 6); | |
| context->drawArrays(PrimitiveMode::Triangles, 0, 6); | |
| setAttributesEnabled(context, glState, prevAttributesMask); | |
| mDrawTextureEnabled = false; | |
| } | |
| Shader *GLES1Renderer::getShader(GLuint handle) const | |
| { | |
| return mShaderPrograms->getShader(handle); | |
| } | |
| Program *GLES1Renderer::getProgram(GLuint handle) const | |
| { | |
| return mShaderPrograms->getProgram(handle); | |
| } | |
| Error GLES1Renderer::compileShader(Context *context, | |
| ShaderType shaderType, | |
| const char *src, | |
| GLuint *shaderOut) | |
| { | |
| rx::ContextImpl *implementation = context->getImplementation(); | |
| const Limitations &limitations = implementation->getNativeLimitations(); | |
| GLuint shader = mShaderPrograms->createShader(implementation, limitations, shaderType); | |
| Shader *shaderObject = getShader(shader); | |
| if (!shaderObject) | |
| return InternalError(); | |
| shaderObject->setSource(1, &src, nullptr); | |
| shaderObject->compile(context); | |
| *shaderOut = shader; | |
| if (!shaderObject->isCompiled()) | |
| { | |
| GLint infoLogLength = shaderObject->getInfoLogLength(); | |
| std::vector<char> infoLog(infoLogLength, 0); | |
| shaderObject->getInfoLog(infoLogLength - 1, nullptr, infoLog.data()); | |
| fprintf(stderr, "GLES1Renderer::%s: Info log: %s\n", __func__, infoLog.data()); | |
| return InternalError() << "GLES1Renderer shader compile failed. Source: " << src | |
| << " Info log: " << infoLog.data(); | |
| } | |
| return NoError(); | |
| } | |
| Error GLES1Renderer::linkProgram(Context *context, | |
| State *glState, | |
| GLuint vertexShader, | |
| GLuint fragmentShader, | |
| const std::unordered_map<GLint, std::string> &attribLocs, | |
| GLuint *programOut) | |
| { | |
| GLuint program = mShaderPrograms->createProgram(context->getImplementation()); | |
| Program *programObject = getProgram(program); | |
| if (!programObject) | |
| { | |
| return InternalError(); | |
| } | |
| *programOut = program; | |
| programObject->attachShader(getShader(vertexShader)); | |
| programObject->attachShader(getShader(fragmentShader)); | |
| for (auto it : attribLocs) | |
| { | |
| GLint index = it.first; | |
| const std::string &name = it.second; | |
| programObject->bindAttributeLocation(index, name.c_str()); | |
| } | |
| ANGLE_TRY(programObject->link(context)); | |
| glState->onProgramExecutableChange(programObject); | |
| if (!programObject->isLinked()) | |
| { | |
| GLint infoLogLength = programObject->getInfoLogLength(); | |
| std::vector<char> infoLog(infoLogLength, 0); | |
| programObject->getInfoLog(infoLogLength - 1, nullptr, infoLog.data()); | |
| return InternalError() << "GLES1Renderer program link failed. Info log: " << infoLog.data(); | |
| } | |
| programObject->detachShader(context, getShader(vertexShader)); | |
| programObject->detachShader(context, getShader(fragmentShader)); | |
| return NoError(); | |
| } | |
| Error GLES1Renderer::initializeRendererProgram(Context *context, State *glState) | |
| { | |
| if (mRendererProgramInitialized) | |
| { | |
| return NoError(); | |
| } | |
| mShaderPrograms = new ShaderProgramManager(); | |
| GLuint vertexShader; | |
| GLuint fragmentShader; | |
| ANGLE_TRY(compileShader(context, ShaderType::Vertex, kGLES1DrawVShader, &vertexShader)); | |
| std::stringstream fragmentStream; | |
| fragmentStream << kGLES1DrawFShaderHeader; | |
| fragmentStream << kGLES1DrawFShaderUniformDefs; | |
| fragmentStream << kGLES1DrawFShaderFunctions; | |
| fragmentStream << kGLES1DrawFShaderMultitexturing; | |
| fragmentStream << kGLES1DrawFShaderMain; | |
| ANGLE_TRY(compileShader(context, ShaderType::Fragment, fragmentStream.str().c_str(), | |
| &fragmentShader)); | |
| std::unordered_map<GLint, std::string> attribLocs; | |
| attribLocs[(GLint)kVertexAttribIndex] = "pos"; | |
| attribLocs[(GLint)kNormalAttribIndex] = "normal"; | |
| attribLocs[(GLint)kColorAttribIndex] = "color"; | |
| attribLocs[(GLint)kPointSizeAttribIndex] = "pointsize"; | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| std::stringstream ss; | |
| ss << "texcoord" << i; | |
| attribLocs[kTextureCoordAttribIndexBase + i] = ss.str(); | |
| } | |
| ANGLE_TRY(linkProgram(context, glState, vertexShader, fragmentShader, attribLocs, | |
| &mProgramState.program)); | |
| mShaderPrograms->deleteShader(context, vertexShader); | |
| mShaderPrograms->deleteShader(context, fragmentShader); | |
| Program *programObject = getProgram(mProgramState.program); | |
| mProgramState.projMatrixLoc = programObject->getUniformLocation("projection"); | |
| mProgramState.modelviewMatrixLoc = programObject->getUniformLocation("modelview"); | |
| mProgramState.textureMatrixLoc = programObject->getUniformLocation("texture_matrix"); | |
| mProgramState.modelviewInvTrLoc = programObject->getUniformLocation("modelview_invtr"); | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| std::stringstream ss2d; | |
| std::stringstream sscube; | |
| ss2d << "tex_sampler" << i; | |
| sscube << "tex_cube_sampler" << i; | |
| mProgramState.tex2DSamplerLocs[i] = programObject->getUniformLocation(ss2d.str().c_str()); | |
| mProgramState.texCubeSamplerLocs[i] = | |
| programObject->getUniformLocation(sscube.str().c_str()); | |
| } | |
| mProgramState.enableTexture2DLoc = programObject->getUniformLocation("enable_texture_2d"); | |
| mProgramState.enableTextureCubeMapLoc = | |
| programObject->getUniformLocation("enable_texture_cube_map"); | |
| mProgramState.textureFormatLoc = programObject->getUniformLocation("texture_format"); | |
| mProgramState.textureEnvModeLoc = programObject->getUniformLocation("texture_env_mode"); | |
| mProgramState.combineRgbLoc = programObject->getUniformLocation("combine_rgb"); | |
| mProgramState.combineAlphaLoc = programObject->getUniformLocation("combine_alpha"); | |
| mProgramState.src0rgbLoc = programObject->getUniformLocation("src0_rgb"); | |
| mProgramState.src0alphaLoc = programObject->getUniformLocation("src0_alpha"); | |
| mProgramState.src1rgbLoc = programObject->getUniformLocation("src1_rgb"); | |
| mProgramState.src1alphaLoc = programObject->getUniformLocation("src1_alpha"); | |
| mProgramState.src2rgbLoc = programObject->getUniformLocation("src2_rgb"); | |
| mProgramState.src2alphaLoc = programObject->getUniformLocation("src2_alpha"); | |
| mProgramState.op0rgbLoc = programObject->getUniformLocation("op0_rgb"); | |
| mProgramState.op0alphaLoc = programObject->getUniformLocation("op0_alpha"); | |
| mProgramState.op1rgbLoc = programObject->getUniformLocation("op1_rgb"); | |
| mProgramState.op1alphaLoc = programObject->getUniformLocation("op1_alpha"); | |
| mProgramState.op2rgbLoc = programObject->getUniformLocation("op2_rgb"); | |
| mProgramState.op2alphaLoc = programObject->getUniformLocation("op2_alpha"); | |
| mProgramState.textureEnvColorLoc = programObject->getUniformLocation("texture_env_color"); | |
| mProgramState.rgbScaleLoc = programObject->getUniformLocation("texture_env_rgb_scale"); | |
| mProgramState.alphaScaleLoc = programObject->getUniformLocation("texture_env_alpha_scale"); | |
| mProgramState.pointSpriteCoordReplaceLoc = | |
| programObject->getUniformLocation("point_sprite_coord_replace"); | |
| mProgramState.enableAlphaTestLoc = programObject->getUniformLocation("enable_alpha_test"); | |
| mProgramState.alphaFuncLoc = programObject->getUniformLocation("alpha_func"); | |
| mProgramState.alphaTestRefLoc = programObject->getUniformLocation("alpha_test_ref"); | |
| mProgramState.shadeModelFlatLoc = programObject->getUniformLocation("shade_model_flat"); | |
| mProgramState.enableLightingLoc = programObject->getUniformLocation("enable_lighting"); | |
| mProgramState.enableRescaleNormalLoc = | |
| programObject->getUniformLocation("enable_rescale_normal"); | |
| mProgramState.enableNormalizeLoc = programObject->getUniformLocation("enable_normalize"); | |
| mProgramState.enableColorMaterialLoc = | |
| programObject->getUniformLocation("enable_color_material"); | |
| mProgramState.materialAmbientLoc = programObject->getUniformLocation("material_ambient"); | |
| mProgramState.materialDiffuseLoc = programObject->getUniformLocation("material_diffuse"); | |
| mProgramState.materialSpecularLoc = programObject->getUniformLocation("material_specular"); | |
| mProgramState.materialEmissiveLoc = programObject->getUniformLocation("material_emissive"); | |
| mProgramState.materialSpecularExponentLoc = | |
| programObject->getUniformLocation("material_specular_exponent"); | |
| mProgramState.lightModelSceneAmbientLoc = | |
| programObject->getUniformLocation("light_model_scene_ambient"); | |
| mProgramState.lightModelTwoSidedLoc = | |
| programObject->getUniformLocation("light_model_two_sided"); | |
| mProgramState.lightEnablesLoc = programObject->getUniformLocation("light_enables"); | |
| mProgramState.lightAmbientsLoc = programObject->getUniformLocation("light_ambients"); | |
| mProgramState.lightDiffusesLoc = programObject->getUniformLocation("light_diffuses"); | |
| mProgramState.lightSpecularsLoc = programObject->getUniformLocation("light_speculars"); | |
| mProgramState.lightPositionsLoc = programObject->getUniformLocation("light_positions"); | |
| mProgramState.lightDirectionsLoc = programObject->getUniformLocation("light_directions"); | |
| mProgramState.lightSpotlightExponentsLoc = | |
| programObject->getUniformLocation("light_spotlight_exponents"); | |
| mProgramState.lightSpotlightCutoffAnglesLoc = | |
| programObject->getUniformLocation("light_spotlight_cutoff_angles"); | |
| mProgramState.lightAttenuationConstsLoc = | |
| programObject->getUniformLocation("light_attenuation_consts"); | |
| mProgramState.lightAttenuationLinearsLoc = | |
| programObject->getUniformLocation("light_attenuation_linears"); | |
| mProgramState.lightAttenuationQuadraticsLoc = | |
| programObject->getUniformLocation("light_attenuation_quadratics"); | |
| mProgramState.fogEnableLoc = programObject->getUniformLocation("enable_fog"); | |
| mProgramState.fogModeLoc = programObject->getUniformLocation("fog_mode"); | |
| mProgramState.fogDensityLoc = programObject->getUniformLocation("fog_density"); | |
| mProgramState.fogStartLoc = programObject->getUniformLocation("fog_start"); | |
| mProgramState.fogEndLoc = programObject->getUniformLocation("fog_end"); | |
| mProgramState.fogColorLoc = programObject->getUniformLocation("fog_color"); | |
| mProgramState.enableClipPlanesLoc = programObject->getUniformLocation("enable_clip_planes"); | |
| mProgramState.clipPlaneEnablesLoc = programObject->getUniformLocation("clip_plane_enables"); | |
| mProgramState.clipPlanesLoc = programObject->getUniformLocation("clip_planes"); | |
| mProgramState.pointRasterizationLoc = programObject->getUniformLocation("point_rasterization"); | |
| mProgramState.pointSizeMinLoc = programObject->getUniformLocation("point_size_min"); | |
| mProgramState.pointSizeMaxLoc = programObject->getUniformLocation("point_size_max"); | |
| mProgramState.pointDistanceAttenuationLoc = | |
| programObject->getUniformLocation("point_distance_attenuation"); | |
| mProgramState.pointSpriteEnabledLoc = programObject->getUniformLocation("point_sprite_enabled"); | |
| mProgramState.enableDrawTextureLoc = programObject->getUniformLocation("enable_draw_texture"); | |
| mProgramState.drawTextureCoordsLoc = programObject->getUniformLocation("draw_texture_coords"); | |
| mProgramState.drawTextureDimsLoc = programObject->getUniformLocation("draw_texture_dims"); | |
| mProgramState.drawTextureNormalizedCropRectLoc = | |
| programObject->getUniformLocation("draw_texture_normalized_crop_rect"); | |
| glState->setProgram(context, programObject); | |
| for (int i = 0; i < kTexUnitCount; i++) | |
| { | |
| setUniform1i(programObject, mProgramState.tex2DSamplerLocs[i], i); | |
| setUniform1i(programObject, mProgramState.texCubeSamplerLocs[i], i + kTexUnitCount); | |
| } | |
| glState->setObjectDirty(GL_PROGRAM); | |
| mRendererProgramInitialized = true; | |
| return NoError(); | |
| } | |
| void GLES1Renderer::setUniform1i(Program *programObject, GLint loc, GLint value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform1iv(loc, 1, &value); | |
| } | |
| void GLES1Renderer::setUniform1iv(Program *programObject, | |
| GLint loc, | |
| GLint count, | |
| const GLint *value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform1iv(loc, count, value); | |
| } | |
| void GLES1Renderer::setUniformMatrix4fv(Program *programObject, | |
| GLint loc, | |
| GLint count, | |
| GLboolean transpose, | |
| const GLfloat *value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniformMatrix4fv(loc, count, transpose, value); | |
| } | |
| void GLES1Renderer::setUniform4fv(Program *programObject, | |
| GLint loc, | |
| GLint count, | |
| const GLfloat *value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform4fv(loc, count, value); | |
| } | |
| void GLES1Renderer::setUniform3fv(Program *programObject, | |
| GLint loc, | |
| GLint count, | |
| const GLfloat *value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform3fv(loc, count, value); | |
| } | |
| void GLES1Renderer::setUniform2fv(Program *programObject, | |
| GLint loc, | |
| GLint count, | |
| const GLfloat *value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform2fv(loc, count, value); | |
| } | |
| void GLES1Renderer::setUniform1f(Program *programObject, GLint loc, GLfloat value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform1fv(loc, 1, &value); | |
| } | |
| void GLES1Renderer::setUniform1fv(Program *programObject, | |
| GLint loc, | |
| GLint count, | |
| const GLfloat *value) | |
| { | |
| if (loc == -1) | |
| return; | |
| programObject->setUniform1fv(loc, count, value); | |
| } | |
| void GLES1Renderer::setAttributesEnabled(Context *context, State *glState, AttributesMask mask) | |
| { | |
| GLES1State &gles1 = glState->gles1(); | |
| ClientVertexArrayType nonTexcoordArrays[] = { | |
| ClientVertexArrayType::Vertex, ClientVertexArrayType::Normal, ClientVertexArrayType::Color, | |
| ClientVertexArrayType::PointSize, | |
| }; | |
| for (const ClientVertexArrayType attrib : nonTexcoordArrays) | |
| { | |
| int index = VertexArrayIndex(attrib, glState->gles1()); | |
| if (mask.test(index)) | |
| { | |
| gles1.setClientStateEnabled(attrib, true); | |
| context->enableVertexAttribArray(index); | |
| } | |
| else | |
| { | |
| gles1.setClientStateEnabled(attrib, false); | |
| context->disableVertexAttribArray(index); | |
| } | |
| } | |
| for (unsigned int i = 0; i < kTexUnitCount; i++) | |
| { | |
| int index = TexCoordArrayIndex(i); | |
| if (mask.test(index)) | |
| { | |
| gles1.setTexCoordArrayEnabled(i, true); | |
| context->enableVertexAttribArray(index); | |
| } | |
| else | |
| { | |
| gles1.setTexCoordArrayEnabled(i, false); | |
| context->disableVertexAttribArray(index); | |
| } | |
| } | |
| } | |
| } // namespace gl |