aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLingfeng Yang <lfy@google.com>2017-07-09 10:58:07 -0700
committerLingfeng Yang <lfy@google.com>2017-07-10 14:26:38 -0700
commit80a3633e673a25d034e01198eef15d64b28a0866 (patch)
treed60b3610e4a29629ac3e034bc994332f8c6c2155
parent2cc4bcd8508ae53860fe85c6489f2b231fa8439a (diff)
downloaddevice_generic_goldfish-opengl-80a3633e673a25d034e01198eef15d64b28a0866.tar.gz
device_generic_goldfish-opengl-80a3633e673a25d034e01198eef15d64b28a0866.tar.bz2
device_generic_goldfish-opengl-80a3633e673a25d034e01198eef15d64b28a0866.zip
Safe glGetBoolean/Integer/Float queries
bug: 63454254 Test: N-CTS dEQP GLES2/3/EGL 100% pass Change-Id: I47de6426d216bf6c83a634b89870ad5ad9ad4dae
-rwxr-xr-xsystem/GLESv2_enc/GL2Encoder.cpp152
-rw-r--r--system/GLESv2_enc/GL2Encoder.h23
2 files changed, 153 insertions, 22 deletions
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 11be3c7f..39e4cdaf 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -285,6 +285,8 @@ GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol)
OVERRIDE(glGetIntegeri_v);
OVERRIDE(glGetInteger64i_v);
+ OVERRIDE(glGetInteger64v);
+ OVERRIDE(glGetBooleani_v);
OVERRIDE(glGetShaderiv);
@@ -356,12 +358,112 @@ GLenum GL2Encoder::s_glGetError(void * self)
GL2Encoder *ctx = (GL2Encoder *)self;
GLenum err = ctx->getError();
if(err != GL_NO_ERROR) {
+ ctx->m_glGetError_enc(ctx); // also clear host error
ctx->setError(GL_NO_ERROR);
return err;
}
return ctx->m_glGetError_enc(self);
+}
+
+class GL2Encoder::ErrorUpdater {
+public:
+ ErrorUpdater(GL2Encoder* ctx) :
+ mCtx(ctx),
+ guest_error(ctx->getError()),
+ host_error(ctx->m_glGetError_enc(ctx)) {
+ // Preserve any existing GL error in the guest:
+ // OpenGL ES 3.0.5 spec:
+ // The command enum GetError( void ); is used to obtain error information.
+ // Each detectable error is assigned a numeric code. When an error is
+ // detected, a flag is set and the code is recorded. Further errors, if
+ // they occur, do not affect this recorded code. When GetError is called,
+ // the code is returned and the flag is cleared, so that a further error
+ // will again record its code. If a call to GetError returns NO_ERROR, then
+ // there has been no detectable error since the last call to GetError (or
+ // since the GL was initialized).
+ if (guest_error == GL_NO_ERROR) {
+ guest_error = host_error;
+ }
+ }
+
+ GLenum getHostErrorAndUpdate() {
+ host_error = mCtx->m_glGetError_enc(mCtx);
+ if (guest_error == GL_NO_ERROR) {
+ guest_error = host_error;
+ }
+ return host_error;
+ }
+
+ void updateGuestErrorState() {
+ mCtx->setError(guest_error);
+ }
+private:
+ GL2Encoder* mCtx;
+ GLenum guest_error;
+ GLenum host_error;
+};
+
+template<class T>
+class GL2Encoder::ScopedQueryUpdate {
+public:
+ ScopedQueryUpdate(GL2Encoder* ctx, uint32_t bytes, T* target) :
+ mCtx(ctx),
+ mBuf(bytes, 0),
+ mTarget(target),
+ mErrorUpdater(ctx) {
+ }
+ T* hostStagingBuffer() {
+ return (T*)&mBuf[0];
+ }
+ ~ScopedQueryUpdate() {
+ GLint hostError = mErrorUpdater.getHostErrorAndUpdate();
+ if (hostError == GL_NO_ERROR) {
+ memcpy(mTarget, &mBuf[0], mBuf.size());
+ }
+ mErrorUpdater.updateGuestErrorState();
+ }
+private:
+ GL2Encoder* mCtx;
+ std::vector<char> mBuf;
+ T* mTarget;
+ ErrorUpdater mErrorUpdater;
+};
+
+void GL2Encoder::safe_glGetBooleanv(GLenum param, GLboolean* val) {
+ ScopedQueryUpdate<GLboolean> query(this, glUtilsParamSize(param) * sizeof(GLboolean), val);
+ m_glGetBooleanv_enc(this, param, query.hostStagingBuffer());
+}
+
+void GL2Encoder::safe_glGetFloatv(GLenum param, GLfloat* val) {
+ ScopedQueryUpdate<GLfloat> query(this, glUtilsParamSize(param) * sizeof(GLfloat), val);
+ m_glGetFloatv_enc(this, param, query.hostStagingBuffer());
+}
+
+void GL2Encoder::safe_glGetIntegerv(GLenum param, GLint* val) {
+ ScopedQueryUpdate<GLint> query(this, glUtilsParamSize(param) * sizeof(GLint), val);
+ m_glGetIntegerv_enc(this, param, query.hostStagingBuffer());
+}
+
+void GL2Encoder::safe_glGetInteger64v(GLenum param, GLint64* val) {
+ ScopedQueryUpdate<GLint64> query(this, glUtilsParamSize(param) * sizeof(GLint64), val);
+ m_glGetInteger64v_enc(this, param, query.hostStagingBuffer());
+}
+
+void GL2Encoder::safe_glGetIntegeri_v(GLenum param, GLuint index, GLint* val) {
+ ScopedQueryUpdate<GLint> query(this, sizeof(GLint), val);
+ m_glGetIntegeri_v_enc(this, param, index, query.hostStagingBuffer());
+}
+
+void GL2Encoder::safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64* val) {
+ ScopedQueryUpdate<GLint64> query(this, sizeof(GLint64), val);
+ m_glGetInteger64i_v_enc(this, param, index, query.hostStagingBuffer());
+}
+
+void GL2Encoder::safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean* val) {
+ ScopedQueryUpdate<GLboolean> query(this, sizeof(GLboolean), val);
+ m_glGetBooleani_v_enc(this, param, index, query.hostStagingBuffer());
}
void GL2Encoder::s_glFlush(void *self)
@@ -553,7 +655,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
case GL_MAX_TEXTURE_IMAGE_UNITS:
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
*ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS);
break;
@@ -566,7 +668,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
case GL_MAX_VERTEX_ATTRIBS:
if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_state->setMaxVertexAttribs(*ptr);
}
break;
@@ -574,7 +676,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_max_vertexAttribStride != 0) {
*ptr = ctx->m_max_vertexAttribStride;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_max_vertexAttribStride = *ptr;
}
break;
@@ -582,7 +684,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_max_cubeMapTextureSize != 0) {
*ptr = ctx->m_max_cubeMapTextureSize;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_max_cubeMapTextureSize = *ptr;
}
break;
@@ -590,7 +692,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_max_renderBufferSize != 0) {
*ptr = ctx->m_max_renderBufferSize;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_max_renderBufferSize = *ptr;
}
break;
@@ -598,7 +700,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_max_textureSize != 0) {
*ptr = ctx->m_max_textureSize;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_max_textureSize = *ptr;
}
break;
@@ -606,7 +708,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_max_3d_textureSize != 0) {
*ptr = ctx->m_max_3d_textureSize;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_max_3d_textureSize = *ptr;
}
break;
@@ -614,7 +716,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_ssbo_offset_align != 0) {
*ptr = ctx->m_ssbo_offset_align;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_ssbo_offset_align = *ptr;
}
break;
@@ -622,7 +724,7 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
if (ctx->m_ubo_offset_align != 0) {
*ptr = ctx->m_ubo_offset_align;
} else {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
ctx->m_ubo_offset_align = *ptr;
}
break;
@@ -639,13 +741,13 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
case GL_MAX_UNIFORM_BUFFER_BINDINGS:
SET_ERROR_IF(ctx->majorVersion() < 3, GL_INVALID_ENUM);
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
break;
case GL_MAX_COLOR_ATTACHMENTS:
case GL_MAX_DRAW_BUFFERS:
SET_ERROR_IF(ctx->majorVersion() < 3 &&
!ctx->hasExtension("GL_EXT_draw_buffers"), GL_INVALID_ENUM);
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
break;
// Not allowed in ES 3.0.
case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
@@ -654,11 +756,11 @@ void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr)
SET_ERROR_IF(ctx->majorVersion() < 3 ||
(ctx->majorVersion() == 3 &&
ctx->minorVersion() == 0), GL_INVALID_ENUM);
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
break;
default:
if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) {
- ctx->m_glGetIntegerv_enc(self, param, ptr);
+ ctx->safe_glGetIntegerv(param, ptr);
}
break;
}
@@ -693,7 +795,7 @@ void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
case GL_MAX_TEXTURE_IMAGE_UNITS:
- ctx->m_glGetFloatv_enc(self, param, ptr);
+ ctx->safe_glGetFloatv(param, ptr);
*ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS);
break;
@@ -706,7 +808,7 @@ void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr)
default:
if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) {
- ctx->m_glGetFloatv_enc(self, param, ptr);
+ ctx->safe_glGetFloatv(param, ptr);
}
break;
}
@@ -748,7 +850,7 @@ void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr)
default:
if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) {
- ctx->m_glGetBooleanv_enc(self, param, ptr);
+ ctx->safe_glGetBooleanv(param, ptr);
}
*ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE;
break;
@@ -1335,7 +1437,7 @@ void GL2Encoder::s_glLinkProgram(void * self, GLuint program)
ctx->m_glLinkProgram_enc(self, program);
GLint linkStatus = 0;
- ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus);
+ ctx->glGetProgramiv(self, program, GL_LINK_STATUS, &linkStatus);
if (!linkStatus) {
return;
}
@@ -4162,7 +4264,7 @@ void GL2Encoder::s_glGetIntegeri_v(void* self, GLenum target, GLuint index, GLin
break;
}
- ctx->m_glGetIntegeri_v_enc(self, target, index, params);
+ ctx->safe_glGetIntegeri_v(target, index, params);
}
void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GLint64* params) {
@@ -4211,7 +4313,17 @@ void GL2Encoder::s_glGetInteger64i_v(void* self, GLenum target, GLuint index, GL
break;
}
- ctx->m_glGetInteger64i_v_enc(self, target, index, params);
+ ctx->safe_glGetInteger64i_v(target, index, params);
+}
+
+void GL2Encoder::s_glGetInteger64v(void* self, GLenum param, GLint64* val) {
+ GL2Encoder *ctx = (GL2Encoder *)self;
+ ctx->safe_glGetInteger64v(param, val);
+}
+
+void GL2Encoder::s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val) {
+ GL2Encoder *ctx = (GL2Encoder *)self;
+ ctx->safe_glGetBooleani_v(param, index, val);
}
void GL2Encoder::s_glGetShaderiv(void* self, GLuint shader, GLenum pname, GLint* params) {
@@ -4282,7 +4394,7 @@ GLuint GL2Encoder::s_glCreateShaderProgramv(void* self, GLenum type, GLsizei cou
ctx->m_shared->associateGLShaderProgram(res, spDataId);
GLint numUniforms = 0;
- ctx->glGetProgramiv(ctx, res, GL_ACTIVE_UNIFORMS, &numUniforms);
+ ctx->glGetProgramiv(self, res, GL_ACTIVE_UNIFORMS, &numUniforms);
ctx->m_shared->initShaderProgramData(res, numUniforms);
GLint maxLength=0;
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 730651fa..3084713e 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -36,7 +36,6 @@ public:
m_currMinorVersion = minor;
m_deviceMajorVersion = deviceMajor;
m_deviceMinorVersion = deviceMinor;
- ALOGD("%s: maj min %d %d\n", __FUNCTION__, major, minor);
}
void setClientStateMakeCurrent(GLClientState *state,
int majorVersion,
@@ -136,6 +135,21 @@ private:
bool isCompleteFbo(GLenum target, const GLClientState* state, GLenum attachment) const;
bool checkFramebufferCompleteness(GLenum target, const GLClientState* state) const;
+ // Utility classes for safe queries that
+ // need access to private class members
+ class ErrorUpdater;
+ template<class T> class ScopedQueryUpdate;
+
+ // General queries
+ void safe_glGetBooleanv(GLenum param, GLboolean *val);
+ void safe_glGetFloatv(GLenum param, GLfloat *val);
+ void safe_glGetIntegerv(GLenum param, GLint *val);
+ void safe_glGetInteger64v(GLenum param, GLint64 *val);
+ void safe_glGetIntegeri_v(GLenum param, GLuint index, GLint *val);
+ void safe_glGetInteger64i_v(GLenum param, GLuint index, GLint64 *val);
+ void safe_glGetBooleani_v(GLenum param, GLuint index, GLboolean *val);
+
+ // API implementation
glGetError_client_proc_t m_glGetError_enc;
static GLenum s_glGetError(void * self);
@@ -169,7 +183,6 @@ private:
glDrawElements_client_proc_t m_glDrawElements_enc;
static void s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices);
-
glGetIntegerv_client_proc_t m_glGetIntegerv_enc;
static void s_glGetIntegerv(void *self, GLenum pname, GLint *ptr);
@@ -179,6 +192,12 @@ private:
glGetBooleanv_client_proc_t m_glGetBooleanv_enc;
static void s_glGetBooleanv(void *self, GLenum pname, GLboolean *ptr);
+ glGetInteger64v_client_proc_t m_glGetInteger64v_enc;
+ static void s_glGetInteger64v(void* self, GLenum param, GLint64* val);
+
+ glGetBooleani_v_client_proc_t m_glGetBooleani_v_enc;
+ static void s_glGetBooleani_v(void* self, GLenum param, GLuint index, GLboolean* val);
+
glVertexAttribPointer_client_proc_t m_glVertexAttribPointer_enc;
static void s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type,
GLboolean normalized, GLsizei stride, const GLvoid * ptr);