diff options
| author | Lingfeng Yang <lfy@google.com> | 2020-09-17 22:14:48 +0000 |
|---|---|---|
| committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-09-17 22:14:48 +0000 |
| commit | 3cee6dfa624d3944e9bf8d5e2d9cb16f988669d7 (patch) | |
| tree | c9a86aeb34010bdb2a4a67753505be3530cddc78 | |
| parent | 452ffebe65e6d0d8db786f16f1adafea466082a4 (diff) | |
| parent | 62054e92be714b2f17aeea2f9347cfa0139f30c2 (diff) | |
| download | device_generic_goldfish-opengl-3cee6dfa624d3944e9bf8d5e2d9cb16f988669d7.tar.gz device_generic_goldfish-opengl-3cee6dfa624d3944e9bf8d5e2d9cb16f988669d7.tar.bz2 device_generic_goldfish-opengl-3cee6dfa624d3944e9bf8d5e2d9cb16f988669d7.zip | |
Merge "Don't try to do robust buffer access checks on non-linked attrib indices"
| -rw-r--r-- | shared/OpenglCodecCommon/GLClientState.cpp | 7 | ||||
| -rw-r--r-- | shared/OpenglCodecCommon/GLClientState.h | 6 | ||||
| -rwxr-xr-x | shared/OpenglCodecCommon/GLSharedGroup.cpp | 62 | ||||
| -rwxr-xr-x | shared/OpenglCodecCommon/GLSharedGroup.h | 11 | ||||
| -rw-r--r-- | shared/OpenglCodecCommon/StateTrackingSupport.h | 8 | ||||
| -rw-r--r-- | shared/OpenglCodecCommon/glUtils.cpp | 94 | ||||
| -rw-r--r-- | shared/OpenglCodecCommon/glUtils.h | 1 | ||||
| -rwxr-xr-x | system/GLESv2_enc/GL2Encoder.cpp | 73 |
8 files changed, 239 insertions, 23 deletions
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp index 039b7632..67758316 100644 --- a/shared/OpenglCodecCommon/GLClientState.cpp +++ b/shared/OpenglCodecCommon/GLClientState.cpp @@ -2406,6 +2406,13 @@ void GLClientState::validateUniform(bool isFloat, bool isUnsigned, GLint columns } } +bool GLClientState::isAttribIndexUsedByProgram(int index) { + auto info = currentAttribValidationInfo.get_const(index); + if (!info) return false; + if (!info->validInProgram) return false; + return true; +} + void GLClientState::addFreshFramebuffer(GLuint name) { FboProps props; props.name = name; diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h index c98190c8..6beeb962 100644 --- a/shared/OpenglCodecCommon/GLClientState.h +++ b/shared/OpenglCodecCommon/GLClientState.h @@ -541,12 +541,14 @@ public: int getMaxColorAttachments() const; int getMaxDrawBuffers() const; - // Uniform validation info + // Uniform/attribute validation info UniformValidationInfo currentUniformValidationInfo; - // TODO: Program uniform validation info + AttribValidationInfo currentAttribValidationInfo;; // Uniform validation api void validateUniform(bool isFloat, bool isUnsigned, GLint columns, GLint rows, GLint location, GLsizei count, GLenum* err); + // Attrib validation + bool isAttribIndexUsedByProgram(int attribIndex); private: void init(); diff --git a/shared/OpenglCodecCommon/GLSharedGroup.cpp b/shared/OpenglCodecCommon/GLSharedGroup.cpp index 848dfdbb..e2ed36cb 100755 --- a/shared/OpenglCodecCommon/GLSharedGroup.cpp +++ b/shared/OpenglCodecCommon/GLSharedGroup.cpp @@ -40,6 +40,7 @@ ProgramData::ProgramData() : m_numIndexes(0), m_numAttributes(0), m_initialized(false) { m_Indexes = NULL; + m_attribIndexes = NULL; m_refcount = 1; m_linkStatus = 0; m_activeUniformBlockCount = 0; @@ -52,8 +53,10 @@ void ProgramData::initProgramData(GLuint numIndexes, GLuint numAttributes) { m_numAttributes = numAttributes; delete [] m_Indexes; + delete [] m_attribIndexes; m_Indexes = new IndexInfo[numIndexes]; + m_attribIndexes = new AttribInfo[m_numAttributes]; } bool ProgramData::isInitialized() { @@ -63,6 +66,7 @@ bool ProgramData::isInitialized() { ProgramData::~ProgramData() { delete [] m_Indexes; + delete [] m_attribIndexes; m_Indexes = NULL; } @@ -80,6 +84,16 @@ void ProgramData::setIndexInfo( m_Indexes[index].samplerValue = 0; } +void ProgramData::setAttribInfo( + GLuint index, GLint attribLoc, GLint size, GLenum type) { + + if (index >= m_numAttributes) return; + + m_attribIndexes[index].attribLoc = attribLoc; + m_attribIndexes[index].size = size; + m_attribIndexes[index].type = type; +} + void ProgramData::setIndexFlags(GLuint index, GLuint flags) { if (index >= m_numIndexes) return; @@ -228,6 +242,27 @@ UniformValidationInfo ProgramData::compileValidationInfo(bool* error) const { return res; } +AttribValidationInfo ProgramData::compileAttribValidationInfo(bool* error) const { + AttribValidationInfo res; + if (!m_attribIndexes) { + *error = true; + return res; + } + + for (GLuint i = 0; i < m_numAttributes; ++i) { + if (m_attribIndexes[i].attribLoc < 0) continue; + + AttribIndexInfo info = { + .validInProgram = true, + }; + + for (GLuint j = 0; j < getAttributeCountOfType(m_attribIndexes[i].type) * m_attribIndexes[i].size ; ++j) { + res.add(m_attribIndexes[i].attribLoc + j, info); + } + } + + return res; +} /***** GLSharedGroup ****/ GLSharedGroup::GLSharedGroup() { } @@ -521,6 +556,19 @@ void GLSharedGroup::setProgramIndexInfo( } } +void GLSharedGroup::setProgramAttribInfo( + GLuint program, GLuint index, GLint attribLoc, + GLint size, GLenum type, const char* name) { + + android::AutoMutex _lock(m_lock); + + ProgramData* pData = getProgramDataLocked(program); + + if (pData) { + pData->setAttribInfo(index,attribLoc,size,type); + } +} + GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location) { android::AutoMutex _lock(m_lock); @@ -801,6 +849,20 @@ UniformValidationInfo GLSharedGroup::getUniformValidationInfo(GLuint program) { return pData->compileValidationInfo(&error); } +AttribValidationInfo GLSharedGroup::getAttribValidationInfo(GLuint program) { + AttribValidationInfo res; + + android::AutoMutex _lock(m_lock); + + ProgramData* pData = + getProgramDataLocked(program); + + if (!pData) return res; + + bool error; (void)error; + return pData->compileAttribValidationInfo(&error); +} + void GLSharedGroup::setProgramLinkStatus(GLuint program, GLint linkStatus) { android::AutoMutex _lock(m_lock); ProgramData* pData = diff --git a/shared/OpenglCodecCommon/GLSharedGroup.h b/shared/OpenglCodecCommon/GLSharedGroup.h index b423951b..807a0065 100755 --- a/shared/OpenglCodecCommon/GLSharedGroup.h +++ b/shared/OpenglCodecCommon/GLSharedGroup.h @@ -76,9 +76,16 @@ private: GLint samplerValue; // only set for sampler uniforms } IndexInfo; + typedef struct _AttribInfo { + GLint attribLoc; + GLint size; + GLenum type; + } AttribInfo; + GLuint m_numIndexes; GLuint m_numAttributes; IndexInfo* m_Indexes; + AttribInfo* m_attribIndexes; bool m_initialized; std::vector<GLuint> m_shaders; @@ -100,6 +107,7 @@ public: bool isInitialized(); virtual ~ProgramData(); void setIndexInfo(GLuint index, GLint base, GLint size, GLenum type); + void setAttribInfo(GLuint index, GLint base, GLint size, GLenum type); void setIndexFlags(GLuint index, GLuint flags); GLuint getIndexForLocation(GLint location); GLenum getTypeForLocation(GLint location); @@ -120,6 +128,7 @@ public: } UniformValidationInfo compileValidationInfo(bool* error) const; + AttribValidationInfo compileAttribValidationInfo(bool* error) const; void setLinkStatus(GLint status) { m_linkStatus = status; } GLint getLinkStatus() { return m_linkStatus; } @@ -210,6 +219,7 @@ public: void deleteProgramData(GLuint program); void deleteProgramDataLocked(GLuint program); void setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name); + void setProgramAttribInfo(GLuint program, GLuint index, GLint attribLoc, GLint size, GLenum type, const char* name); GLenum getProgramUniformType(GLuint program, GLint location); GLint getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const; bool setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target); @@ -233,6 +243,7 @@ public: // Validation info UniformValidationInfo getUniformValidationInfo(GLuint program); + AttribValidationInfo getAttribValidationInfo(GLuint program); void setProgramLinkStatus(GLuint program, GLint linkStatus); GLint getProgramLinkStatus(GLuint program); diff --git a/shared/OpenglCodecCommon/StateTrackingSupport.h b/shared/OpenglCodecCommon/StateTrackingSupport.h index c6715c4e..b742c131 100644 --- a/shared/OpenglCodecCommon/StateTrackingSupport.h +++ b/shared/OpenglCodecCommon/StateTrackingSupport.h @@ -74,7 +74,8 @@ private: Storage mStorage; }; -// A structure for fast validation of uniform uploads and other uniform related api calls. +// Structures for fast validation of uniforms/attribs. + struct UniformLocationInfo { bool valid = false; uint32_t columns; @@ -86,7 +87,12 @@ struct UniformLocationInfo { bool isBool; }; +struct AttribIndexInfo { + bool validInProgram = false; +}; + using UniformValidationInfo = android::base::HybridComponentManager<1000, uint32_t, UniformLocationInfo>; +using AttribValidationInfo = android::base::HybridComponentManager<16, uint32_t, AttribIndexInfo>; using LastQueryTargetInfo = android::base::HybridComponentManager<1000, uint32_t, uint32_t>; diff --git a/shared/OpenglCodecCommon/glUtils.cpp b/shared/OpenglCodecCommon/glUtils.cpp index de621393..a6b0b7c8 100644 --- a/shared/OpenglCodecCommon/glUtils.cpp +++ b/shared/OpenglCodecCommon/glUtils.cpp @@ -287,6 +287,100 @@ uint32_t getRowsOfType(GLenum type) { } } +uint32_t getAttributeCountOfType(GLenum type) { + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_HALF_FLOAT: + case GL_HALF_FLOAT_OES: + case GL_IMAGE_2D: + case GL_IMAGE_3D: + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + case GL_FIXED: + case GL_BOOL: + return 1; +#ifdef GL_DOUBLE + case GL_DOUBLE: + case GL_DOUBLE_VEC2: + case GL_DOUBLE_VEC3: + case GL_DOUBLE_VEC4: + return 1; + case GL_DOUBLE_MAT2: + case GL_DOUBLE_MAT2x3: + case GL_DOUBLE_MAT2x4: + return 4; + case GL_DOUBLE_MAT3: + case GL_DOUBLE_MAT3x2: + case GL_DOUBLE_MAT3x4: + return 6; + case GL_DOUBLE_MAT4: + case GL_DOUBLE_MAT4x2: + case GL_DOUBLE_MAT4x3: + return 8; +#endif + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_BOOL_VEC2: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_BOOL_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 1; + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + return 2; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + return 3; + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 4; + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_CUBE_SHADOW: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_IMAGE_CUBE: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D: + case GL_INT_IMAGE_3D: + case GL_INT_IMAGE_CUBE: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + default: + return 1; + } +} + size_t glSizeof(GLenum type) { size_t retval = 0; diff --git a/shared/OpenglCodecCommon/glUtils.h b/shared/OpenglCodecCommon/glUtils.h index 489ac188..09081c2f 100644 --- a/shared/OpenglCodecCommon/glUtils.h +++ b/shared/OpenglCodecCommon/glUtils.h @@ -63,6 +63,7 @@ typedef enum { bool isBoolType(GLenum type); uint32_t getColumnsOfType(GLenum type); uint32_t getRowsOfType(GLenum type); + uint32_t getAttributeCountOfType(GLenum type); size_t glSizeof(GLenum type); size_t glUtilsParamSize(GLenum param); void glUtilsPackPointerData(unsigned char *dst, unsigned char *str, diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp index 919fdef1..cca18a98 100755 --- a/system/GLESv2_enc/GL2Encoder.cpp +++ b/system/GLESv2_enc/GL2Encoder.cpp @@ -1319,20 +1319,24 @@ void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClient } if (state.elementSize == 0) { // The vertex attribute array is uninitialized. Abandon it. - ALOGE("a vertex attribute array is uninitialized. Skipping corresponding vertex attribute."); this->m_glDisableVertexAttribArray_enc(this, i); continue; } m_glEnableVertexAttribArray_enc(this, i); if (datalen && (!offset || !((unsigned char*)offset + firstIndex))) { - ALOGD("%s: bad offset / len!!!!!", __FUNCTION__); continue; } + + unsigned char* data = (unsigned char*)offset + firstIndex; + if (!m_state->isAttribIndexUsedByProgram(i)) { + continue; + } + if (state.isInt) { - this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, (unsigned char *)offset + firstIndex, datalen); + this->glVertexAttribIPointerDataAEMU(this, i, state.size, state.type, stride, data, datalen); } else { - this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, (unsigned char *)offset + firstIndex, datalen); + this->glVertexAttribPointerData(this, i, state.size, state.type, state.normalized, stride, data, datalen); } } else { const BufferData* buf = m_shared->getBufferData(bufferObject); @@ -1347,20 +1351,24 @@ void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count, bool hasClient if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) { if (hasClientArrays) { m_glEnableVertexAttribArray_enc(this, i); - if (state.isInt) { - this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex); - } else { - this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex); + if (firstIndex) { + if (state.isInt) { + this->glVertexAttribIPointerOffsetAEMU(this, i, state.size, state.type, stride, offset + firstIndex); + } else { + this->glVertexAttribPointerOffset(this, i, state.size, state.type, state.normalized, stride, offset + firstIndex); + } } } } else { - ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf); - if (buf) { - ALOGE("Out of bounds vertex attribute info: " - "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u", - hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen); + if (m_state->isAttribIndexUsedByProgram(i)) { + ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=%p", buf); + if (buf) { + ALOGE("Out of bounds vertex attribute info: " + "clientArray? %d attribute %d vbo %u allocedBufferSize %u bufferDataSpecified? %d wantedStart %u wantedEnd %u", + hasClientArrays, i, bufferObject, (unsigned int)buf->m_size, buf != NULL, firstIndex, firstIndex + bufLen); + } + m_glDisableVertexAttribArray_enc(this, i); } - m_glDisableVertexAttribArray_enc(this, i); } } } else { @@ -1909,11 +1917,14 @@ void GL2Encoder::s_glLinkProgram(void * self, GLuint program) //get the length of the longest uniform name GLint maxLength=0; + GLint maxAttribLength=0; ctx->m_glGetProgramiv_enc(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); + ctx->m_glGetProgramiv_enc(self, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLength); GLint size; GLenum type; - GLchar *name = new GLchar[maxLength+1]; + size_t bufLen = maxLength > maxAttribLength ? maxLength : maxAttribLength; + GLchar *name = new GLchar[bufLen + 1]; GLint location; //for each active uniform, get its size and starting location. for (GLint i=0 ; i<numUniforms ; ++i) @@ -1923,6 +1934,12 @@ void GL2Encoder::s_glLinkProgram(void * self, GLuint program) ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name); } + for (GLint i = 0; i < numAttributes; ++i) { + ctx->m_glGetActiveAttrib_enc(self, program, i, maxAttribLength, NULL, &size, &type, name); + location = ctx->m_glGetAttribLocation_enc(self, program, name); + ctx->m_shared->setProgramAttribInfo(program, i, location, size, type, name); + } + if (ctx->majorVersion() > 2) { GLint numBlocks; ctx->m_glGetProgramiv_enc(ctx, program, GL_ACTIVE_UNIFORM_BLOCKS, &numBlocks); @@ -2219,6 +2236,7 @@ void GL2Encoder::s_glUseProgram(void *self, GLuint program) if (program) { ctx->m_state->currentUniformValidationInfo = ctx->m_shared->getUniformValidationInfo(program); + ctx->m_state->currentAttribValidationInfo = ctx->m_shared->getAttribValidationInfo(program); } } @@ -5321,7 +5339,7 @@ void GL2Encoder::s_glActiveShaderProgram(void* self, GLuint pipeline, GLuint pro } } -GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei count, const char** strings) { +GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum shaderType, GLsizei count, const char** strings) { GLint* length = NULL; GL2Encoder* ctx = (GL2Encoder*)self; @@ -5342,7 +5360,7 @@ GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei cou return -1; } - GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, type, count, str, len + 1); + GLuint res = ctx->glCreateShaderProgramvAEMU(ctx, shaderType, count, str, len + 1); delete [] str; // Phase 2: do glLinkProgram-related initialization for locationWorkARound @@ -5363,14 +5381,23 @@ GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei cou ctx->m_shared->initShaderProgramData(res, numUniforms, numAttributes); GLint maxLength=0; + GLint maxAttribLength=0; ctx->m_glGetProgramiv_enc(self, res, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); + ctx->m_glGetProgramiv_enc(self, res, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttribLength); - GLint size; GLenum uniformType; GLchar* name = new GLchar[maxLength + 1]; + size_t bufLen = maxLength > maxAttribLength ? maxLength : maxAttribLength; + GLint size; GLenum type; GLchar *name = new GLchar[bufLen + 1]; for (GLint i = 0; i < numUniforms; ++i) { - ctx->m_glGetActiveUniform_enc(self, res, i, maxLength, NULL, &size, &uniformType, name); + ctx->m_glGetActiveUniform_enc(self, res, i, maxLength, NULL, &size, &type, name); GLint location = ctx->m_glGetUniformLocation_enc(self, res, name); - ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, uniformType, name); + ctx->m_shared->setShaderProgramIndexInfo(res, i, location, size, type, name); + } + + for (GLint i = 0; i < numAttributes; ++i) { + ctx->m_glGetActiveAttrib_enc(self, res, i, maxAttribLength, NULL, &size, &type, name); + GLint location = ctx->m_glGetAttribLocation_enc(self, res, name); + ctx->m_shared->setProgramAttribInfo(res, i, location, size, type, name); } GLint numBlocks; @@ -5636,6 +5663,11 @@ void GL2Encoder::s_glUseProgramStages(void *self, GLuint pipeline, GLbitfield st // Otherwise, update host texture 2D bindings. ctx->updateHostTexture2DBindingsFromProgramData(program); + + if (program) { + ctx->m_state->currentUniformValidationInfo = ctx->m_shared->getUniformValidationInfo(program); + ctx->m_state->currentAttribValidationInfo = ctx->m_shared->getAttribValidationInfo(program); + } } void GL2Encoder::s_glBindProgramPipeline(void* self, GLuint pipeline) @@ -6208,6 +6240,7 @@ void GL2Encoder::s_glBindAttribLocation(void *self , GLuint program, GLuint inde SET_ERROR_IF(index > maxVertexAttribs, GL_INVALID_VALUE); SET_ERROR_IF(name && !strncmp("gl_", name, 3), GL_INVALID_OPERATION); + fprintf(stderr, "%s: bind attrib %u name %s\n", __func__, index, name); ctx->m_glBindAttribLocation_enc(ctx, program, index, name); } |
