13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES Utilities 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------------ 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief SGLR shader program. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sglrShaderProgram.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace sglr 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace pdec 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 313c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration::ShaderProgramDeclaration (void) 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_geometryDecl (rr::GEOMETRYSHADERINPUTTYPE_LAST, rr::GEOMETRYSHADEROUTPUTTYPE_LAST, 0, 0) 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_vertexShaderSet (false) 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_fragmentShaderSet (false) 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_geometryShaderSet (false) 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 393c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexAttribute& v) 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_vertexAttributes.push_back(v); 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexToFragmentVarying& v) 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_vertexToFragmentVaryings.push_back(v); 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexToGeometryVarying& v) 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_vertexToGeometryVaryings.push_back(v); 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometryToFragmentVarying& v) 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryToFragmentVaryings.push_back(v); 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const FragmentOutput& v) 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_fragmentOutputs.push_back(v); 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 693c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const Uniform& v) 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_uniforms.push_back(v); 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 753c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const VertexSource& c) 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_vertexShaderSet); 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_vertexSource = c.source; 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_vertexShaderSet = true; 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const FragmentSource& c) 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_fragmentShaderSet); 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_fragmentSource = c.source; 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_fragmentShaderSet = true; 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 913c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometrySource& c) 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_geometryShaderSet); 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometrySource = c.source; 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryShaderSet = true; 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgramDeclaration& pdec::ShaderProgramDeclaration::operator<< (const GeometryShaderDeclaration& c) 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryDecl = c; 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ShaderProgramDeclaration::valid (void) const 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_vertexShaderSet || !m_fragmentShaderSet) 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_fragmentOutputs.empty()) 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (hasGeometryShader()) 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_geometryDecl.inputType == rr::GEOMETRYSHADERINPUTTYPE_LAST || 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryDecl.outputType == rr::GEOMETRYSHADEROUTPUTTYPE_LAST) 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_geometryDecl.inputType != rr::GEOMETRYSHADERINPUTTYPE_LAST || 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryDecl.outputType != rr::GEOMETRYSHADEROUTPUTTYPE_LAST || 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryDecl.numOutputVertices != 0 || 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_geometryDecl.numInvocations != 0) 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} //pdec 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgram::ShaderProgram (const pdec::ShaderProgramDeclaration& decl) 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : rr::VertexShader (decl.getVertexInputCount(), decl.getVertexOutputCount()) 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , rr::GeometryShader (decl.getGeometryInputCount(), 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.getGeometryOutputCount(), 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.m_geometryDecl.inputType, 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.m_geometryDecl.outputType, 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.m_geometryDecl.numOutputVertices, 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry decl.m_geometryDecl.numInvocations) 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , rr::FragmentShader (decl.getFragmentInputCount(), decl.getFragmentOutputCount()) 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_attributeNames (decl.getVertexInputCount()) 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_uniforms (decl.m_uniforms.size()) 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_vertSrc (decl.m_vertexSource) 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_fragSrc (decl.m_fragmentSource) 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_geomSrc (decl.hasGeometryShader() ? (decl.m_geometrySource) : ("")) 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_hasGeometryShader (decl.hasGeometryShader()) 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(decl.valid()); 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set up shader IO 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < decl.m_vertexAttributes.size(); ++ndx) 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::VertexShader::m_inputs[ndx].type = decl.m_vertexAttributes[ndx].type; 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_attributeNames[ndx] = decl.m_vertexAttributes[ndx].name; 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_hasGeometryShader) 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < decl.m_vertexToGeometryVaryings.size(); ++ndx) 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::VertexShader::m_outputs[ndx].type = decl.m_vertexToGeometryVaryings[ndx].type; 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::VertexShader::m_outputs[ndx].flatshade = decl.m_vertexToGeometryVaryings[ndx].flatshade; 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::GeometryShader::m_inputs[ndx] = this->rr::VertexShader::m_outputs[ndx]; 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < decl.m_geometryToFragmentVaryings.size(); ++ndx) 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::GeometryShader::m_outputs[ndx].type = decl.m_geometryToFragmentVaryings[ndx].type; 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::GeometryShader::m_outputs[ndx].flatshade = decl.m_geometryToFragmentVaryings[ndx].flatshade; 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::FragmentShader::m_inputs[ndx] = this->rr::GeometryShader::m_outputs[ndx]; 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < decl.m_vertexToFragmentVaryings.size(); ++ndx) 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::VertexShader::m_outputs[ndx].type = decl.m_vertexToFragmentVaryings[ndx].type; 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::VertexShader::m_outputs[ndx].flatshade = decl.m_vertexToFragmentVaryings[ndx].flatshade; 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::FragmentShader::m_inputs[ndx] = this->rr::VertexShader::m_outputs[ndx]; 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < decl.m_fragmentOutputs.size(); ++ndx) 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->rr::FragmentShader::m_outputs[ndx].type = decl.m_fragmentOutputs[ndx].type; 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set up uniforms 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < decl.m_uniforms.size(); ++ndx) 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->m_uniforms[ndx].name = decl.m_uniforms[ndx].name; 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry this->m_uniforms[ndx].type = decl.m_uniforms[ndx].type; 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderProgram::~ShaderProgram (void) 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst UniformSlot& ShaderProgram::getUniformByName (const char* name) const 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(name); 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (size_t ndx = 0; ndx < m_uniforms.size(); ++ndx) 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_uniforms[ndx].name == std::string(name)) 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_uniforms[ndx]; 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!"Invalid uniform name, uniform not found."); 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_uniforms[0]; 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderProgram::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(output); 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(verticesIn && packets && numPackets && invocationID); 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Should never be called. 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(DE_FALSE); 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // sglr 225