Commit fd7c3b52 by jchen10 Committed by Commit Bot

ES31: Add glGetProgramResourceName API

Add API entry and validation checks(GLES 3.1 section 7.3). Add the first 2 interfaces(PROGRAM_INPUT and PROGRAM_OUTPUT) implementation. BUG=angleproject:1920 Change-Id: Ide7d5ad40a611a091c3dffab47fd31da57b69f1d Reviewed-on: https://chromium-review.googlesource.com/457523 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent ec9232bd
......@@ -2049,10 +2049,21 @@ void Context::programPathFragmentInputGen(GLuint program,
GLuint Context::getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name)
{
gl::Program *programObject = getProgram(program);
const auto *programObject = getProgram(program);
return QueryProgramResourceIndex(programObject, programInterface, name);
}
void Context::getProgramResourceName(GLuint program,
GLenum programInterface,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name)
{
const auto *programObject = getProgram(program);
QueryProgramResourceName(programObject, programInterface, index, bufSize, length, name);
}
void Context::handleError(const Error &error)
{
if (error.isError())
......
......@@ -194,6 +194,12 @@ class Context final : public ValidationContext
void programParameteri(GLuint program, GLenum pname, GLint value);
GLuint getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name);
void getProgramResourceName(GLuint program,
GLenum programInterface,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name);
Buffer *getBuffer(GLuint handle) const;
FenceNV *getFenceNV(GLuint handle);
......
......@@ -159,6 +159,18 @@ GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string
return GL_INVALID_INDEX;
}
void CopyStringToBuffer(GLchar *buffer, const std::string &string, GLsizei bufSize, GLsizei *length)
{
ASSERT(bufSize > 0);
strncpy(buffer, string.c_str(), bufSize);
buffer[bufSize - 1] = '\0';
if (length)
{
*length = static_cast<GLsizei>(strlen(buffer));
}
}
} // anonymous namespace
const char *const g_fakepath = "C:\\fakepath";
......@@ -1196,7 +1208,12 @@ bool Program::isAttribLocationActive(size_t attribLocation) const
return mState.mActiveAttribLocationsMask[attribLocation];
}
void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
void Program::getActiveAttribute(GLuint index,
GLsizei bufsize,
GLsizei *length,
GLint *size,
GLenum *type,
GLchar *name) const
{
if (!mLinked)
{
......@@ -1220,15 +1237,7 @@ void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length,
if (bufsize > 0)
{
const char *string = attrib.name.c_str();
strncpy(name, string, bufsize);
name[bufsize - 1] = '\0';
if (length)
{
*length = static_cast<GLsizei>(strlen(name));
}
CopyStringToBuffer(name, attrib.name, bufsize, length);
}
// Always a single 'type' instance
......@@ -1281,6 +1290,50 @@ GLuint Program::getOutputResourceIndex(const GLchar *name) const
return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
}
size_t Program::getOutputResourceCount() const
{
return (mLinked ? mState.mOutputVariables.size() : 0);
}
void Program::getInputResourceName(GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name) const
{
GLint size;
GLenum type;
getActiveAttribute(index, bufSize, length, &size, &type, name);
}
void Program::getOutputResourceName(GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name) const
{
if (length)
{
*length = 0;
}
if (!mLinked)
{
if (bufSize > 0)
{
name[0] = '\0';
}
return;
}
ASSERT(index < mState.mOutputVariables.size());
const auto &output = mState.mOutputVariables[index];
if (bufSize > 0)
{
std::string nameWithArray = (output.isArray() ? output.name + "[0]" : output.name);
CopyStringToBuffer(name, nameWithArray, bufSize, length);
}
}
GLint Program::getFragDataLocation(const std::string &name) const
{
std::string baseName(name);
......@@ -1316,14 +1369,7 @@ void Program::getActiveUniform(GLuint index,
{
string += "[0]";
}
strncpy(name, string.c_str(), bufsize);
name[bufsize - 1] = '\0';
if (length)
{
*length = static_cast<GLsizei>(strlen(name));
}
CopyStringToBuffer(name, string, bufsize, length);
}
*size = uniform.elementCount();
......@@ -1699,14 +1745,7 @@ void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSiz
{
string += ArrayString(uniformBlock.arrayElement);
}
strncpy(uniformBlockName, string.c_str(), bufSize);
uniformBlockName[bufSize - 1] = '\0';
if (length)
{
*length = static_cast<GLsizei>(strlen(uniformBlockName));
}
CopyStringToBuffer(uniformBlockName, string, bufSize, length);
}
}
......
......@@ -319,12 +319,18 @@ class Program final : angle::NonCopyable, public LabeledObject
GLuint getAttributeLocation(const std::string &name) const;
bool isAttribLocationActive(size_t attribLocation) const;
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
void getActiveAttribute(GLuint index,
GLsizei bufsize,
GLsizei *length,
GLint *size,
GLenum *type,
GLchar *name) const;
GLint getActiveAttributeCount() const;
GLint getActiveAttributeMaxLength() const;
const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; }
GLint getFragDataLocation(const std::string &name) const;
size_t getOutputResourceCount() const;
void getActiveUniform(GLuint index,
GLsizei bufsize,
......@@ -418,6 +424,9 @@ class Program final : angle::NonCopyable, public LabeledObject
GLuint getInputResourceIndex(const GLchar *name) const;
GLuint getOutputResourceIndex(const GLchar *name) const;
bool isValidResourceIndex(GLenum programInterface, GLuint index) const;
void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
class Bindings final : angle::NonCopyable
{
......
......@@ -996,6 +996,37 @@ GLuint QueryProgramResourceIndex(const Program *program,
}
}
void QueryProgramResourceName(const Program *program,
GLenum programInterface,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name)
{
switch (programInterface)
{
case GL_PROGRAM_INPUT:
program->getInputResourceName(index, bufSize, length, name);
break;
case GL_PROGRAM_OUTPUT:
program->getOutputResourceName(index, bufSize, length, name);
break;
// TODO(Jie): more interfaces.
case GL_UNIFORM:
case GL_UNIFORM_BLOCK:
case GL_TRANSFORM_FEEDBACK_VARYING:
case GL_BUFFER_VARIABLE:
case GL_SHADER_STORAGE_BLOCK:
UNIMPLEMENTED();
break;
default:
UNREACHABLE();
}
}
} // namespace gl
namespace egl
......
......@@ -113,6 +113,13 @@ GLuint QueryProgramResourceIndex(const Program *program,
GLenum programInterface,
const GLchar *name);
void QueryProgramResourceName(const Program *program,
GLenum programInterface,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name);
} // namespace gl
namespace egl
......
......@@ -41,6 +41,33 @@ bool ValidateNamedProgramInterface(GLenum programInterface)
}
}
bool ValidateProgramResourceIndex(const Program *programObject,
GLenum programInterface,
GLuint index)
{
switch (programInterface)
{
case GL_PROGRAM_INPUT:
return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
case GL_PROGRAM_OUTPUT:
return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
// TODO(Jie): more interfaces.
case GL_UNIFORM:
case GL_UNIFORM_BLOCK:
case GL_TRANSFORM_FEEDBACK_VARYING:
case GL_BUFFER_VARIABLE:
case GL_SHADER_STORAGE_BLOCK:
UNIMPLEMENTED();
return false;
default:
UNREACHABLE();
return false;
}
}
} // anonymous namespace
bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
......@@ -700,4 +727,46 @@ bool ValidateVertexAttribBinding(ValidationContext *context,
return true;
}
bool ValidateGetProgramResourceName(Context *context,
GLuint program,
GLenum programInterface,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name)
{
if (context->getClientVersion() < ES_3_1)
{
context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
return false;
}
Program *programObject = GetValidProgram(context, program);
if (programObject == nullptr)
{
return false;
}
if (!ValidateNamedProgramInterface(programInterface))
{
context->handleError(
Error(GL_INVALID_ENUM, "Invalid program interface: 0x%X", programInterface));
return false;
}
if (!ValidateProgramResourceIndex(programObject, programInterface, index))
{
context->handleError(Error(GL_INVALID_VALUE, "Invalid index: %d", index));
return false;
}
if (bufSize < 0)
{
context->handleError(Error(GL_INVALID_VALUE, "Invalid bufSize: %d", bufSize));
return false;
}
return true;
}
} // namespace gl
......@@ -61,6 +61,13 @@ bool ValidateGetProgramResourceIndex(Context *context,
GLuint program,
GLenum programInterface,
const GLchar *name);
bool ValidateGetProgramResourceName(Context *context,
GLuint program,
GLenum programInterface,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLchar *name);
bool ValidateBindVertexBuffer(ValidationContext *context,
GLuint bindingIndex,
......
......@@ -169,11 +169,13 @@ void GL_APIENTRY GetProgramResourceName(GLuint program,
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->skipValidation())
if (!context->skipValidation() &&
!ValidateGetProgramResourceName(context, program, programInterface, index, bufSize,
length, name))
{
context->handleError(Error(GL_INVALID_OPERATION, "Entry point not implemented"));
return;
}
UNIMPLEMENTED();
context->getProgramResourceName(program, programInterface, index, bufSize, length, name);
}
}
......
......@@ -40,7 +40,7 @@ TEST_P(ProgramInterfaceTestES31, GetResourceIndex)
" gl_Position = position;\n"
"}";
const std::string fragmentShaderSource =
const std::string &fragmentShaderSource =
"#version 310 es\n"
"precision highp float;\n"
"uniform vec4 color;\n"
......@@ -72,5 +72,67 @@ TEST_P(ProgramInterfaceTestES31, GetResourceIndex)
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// Tests glGetProgramResourceName.
TEST_P(ProgramInterfaceTestES31, GetResourceName)
{
const std::string &vertexShaderSource =
"#version 310 es\n"
"precision highp float;\n"
"in highp vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}";
const std::string &fragmentShaderSource =
"#version 310 es\n"
"precision highp float;\n"
"uniform vec4 color;\n"
"out vec4 oColor[4];\n"
"void main()\n"
"{\n"
" oColor[0] = color;\n"
"}";
ANGLE_GL_PROGRAM(program, vertexShaderSource, fragmentShaderSource);
GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
EXPECT_GL_NO_ERROR();
EXPECT_NE(GL_INVALID_INDEX, index);
GLchar name[64];
GLsizei length;
glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, sizeof(name), &length, name);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(8, length);
EXPECT_EQ("position", std::string(name));
glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, 4, &length, name);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(3, length);
EXPECT_EQ("pos", std::string(name));
glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, -1, &length, name);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
glGetProgramResourceName(program, GL_PROGRAM_INPUT, GL_INVALID_INDEX, sizeof(name), &length,
name);
EXPECT_GL_ERROR(GL_INVALID_VALUE);
index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
EXPECT_GL_NO_ERROR();
EXPECT_NE(GL_INVALID_INDEX, index);
glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, sizeof(name), &length, name);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(9, length);
EXPECT_EQ("oColor[0]", std::string(name));
glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, 8, &length, name);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(7, length);
EXPECT_EQ("oColor[", std::string(name));
}
ANGLE_INSTANTIATE_TEST(ProgramInterfaceTestES31, ES31_OPENGL(), ES31_D3D11(), ES31_OPENGLES());
} // anonymous namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment