From d6f18cdf8055620b097933a65be30117c9284b6f Mon Sep 17 00:00:00 2001 From: Stas Gurtovoy Date: Thu, 7 Jul 2011 15:16:47 +0300 Subject: [PATCH] opengl emulator: Added gl error tracking on the guest (encoder) Sometimes we need to check parameter values before encoding to prevent crashes, for example: glDeleteBufferes(-1, ptr); - would crash For that we need to check some gl errors on the guest. The change adds error state to the encoder and also adds new feature to emugen which allows to insert parameter check code into the attribute file. Added such parameter check code in the appropiate gl functions in gl.attrib and gl2.attrib Change-Id: I7f317df52ac8fbd96979100a1031cf023a0b49d3 --- .../opengl/host/tools/emugen/ApiGen.cpp | 13 +++++++++++++ .../opengl/host/tools/emugen/EntryPoint.cpp | 18 ++++++++++++++++++ tools/emulator/opengl/host/tools/emugen/Var.h | 9 +++++++-- .../shared/OpenglCodecCommon/gl_base_types.h | 11 +++++++++++ .../opengl/system/GLESv1_enc/GLEncoder.cpp | 14 ++++++++++++++ .../opengl/system/GLESv1_enc/GLEncoder.h | 6 ++++++ .../opengl/system/GLESv1_enc/gl.attrib | 12 ++++++++++++ .../opengl/system/GLESv2_enc/GL2Encoder.cpp | 15 +++++++++++++++ .../opengl/system/GLESv2_enc/GL2Encoder.h | 7 +++++++ .../opengl/system/GLESv2_enc/gl2.attrib | 10 ++++++++++ 10 files changed, 113 insertions(+), 2 deletions(-) diff --git a/tools/emulator/opengl/host/tools/emugen/ApiGen.cpp b/tools/emulator/opengl/host/tools/emugen/ApiGen.cpp index 9818e5db4..3df3107a9 100644 --- a/tools/emulator/opengl/host/tools/emugen/ApiGen.cpp +++ b/tools/emulator/opengl/host/tools/emugen/ApiGen.cpp @@ -165,6 +165,12 @@ int ApiGen::genContext(const std::string & filename, SideType side) // init function fprintf(fp, "\tint initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);\n"); + //client site set error virtual func + if (side == CLIENT_SIDE) { + fprintf(fp, "\tvirtual void setError(unsigned int error){};\n"); + fprintf(fp, "\tvirtual unsigned int getError(){ return 0; };\n"); + } + fprintf(fp, "};\n"); fprintf(fp, "\n#endif\n"); @@ -222,6 +228,13 @@ int ApiGen::genEntryPoints(const std::string & filename, SideType side) bool shouldReturn = !e->retval().isVoid(); bool shouldCallWithContext = (side == CLIENT_SIDE); + //param check + if (shouldCallWithContext) { + for (size_t j=0; jvars().size(); j++) { + if (e->vars()[j].paramCheckExpression() != "") + fprintf(fp, "\t%s\n", e->vars()[j].paramCheckExpression().c_str()); + } + } fprintf(fp, "\t %sctx->%s(%s", shouldReturn ? "return " : "", e->name().c_str(), diff --git a/tools/emulator/opengl/host/tools/emugen/EntryPoint.cpp b/tools/emulator/opengl/host/tools/emugen/EntryPoint.cpp index 03410272e..413b56af6 100644 --- a/tools/emulator/opengl/host/tools/emugen/EntryPoint.cpp +++ b/tools/emulator/opengl/host/tools/emugen/EntryPoint.cpp @@ -225,6 +225,24 @@ int EntryPoint::setAttribute(const std::string &line, size_t lc) // set the size expression into var pos = last; v->setLenExpression(line.substr(pos)); + } else if (token == "param_check") { + pos = last; + std::string varname = getNextToken(line, pos, &last, WHITESPACE); + + if (varname.size() == 0) { + fprintf(stderr, "ERROR: %u: Missing variable name in 'param_check' attribute\n", (unsigned int)lc); + return -1; + } + Var * v = var(varname); + if (v == NULL) { + fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n", + (unsigned int)lc, varname.c_str(), name().c_str()); + return -2; + } + // set the size expression into var + pos = last; + v->setParamCheckExpression(line.substr(pos)); + } else if (token == "dir") { pos = last; std::string varname = getNextToken(line, pos, &last, WHITESPACE); diff --git a/tools/emulator/opengl/host/tools/emugen/Var.h b/tools/emulator/opengl/host/tools/emugen/Var.h index ba74cea48..c9735c714 100644 --- a/tools/emulator/opengl/host/tools/emugen/Var.h +++ b/tools/emulator/opengl/host/tools/emugen/Var.h @@ -30,7 +30,8 @@ public: m_lenExpression(""), m_pointerDir(POINTER_IN), m_nullAllowed(false), - m_packExpression("") + m_packExpression(""), + m_paramCheckExpression("") { } @@ -45,7 +46,8 @@ public: m_lenExpression(lenExpression), m_pointerDir(dir), m_nullAllowed(false), - m_packExpression(packExpression) + m_packExpression(packExpression), + m_paramCheckExpression("") { } @@ -67,8 +69,10 @@ public: bool isVoid() const { return ((m_type->bytes() == 0) && (!m_type->isPointer())); } const std::string & lenExpression() const { return m_lenExpression; } const std::string & packExpression() const { return(m_packExpression); } + const std::string & paramCheckExpression() const { return m_paramCheckExpression; } void setLenExpression(const std::string & lenExpression) { m_lenExpression = lenExpression; } void setPackExpression(const std::string & packExpression) { m_packExpression = packExpression; } + void setParamCheckExpression(const std::string & paramCheckExpression) { m_paramCheckExpression = paramCheckExpression; } void setPointerDir(PointerDir dir) { m_pointerDir = dir; } PointerDir pointerDir() { return m_pointerDir; } void setNullAllowed(bool state) { m_nullAllowed = state; } @@ -84,6 +88,7 @@ private: PointerDir m_pointerDir; bool m_nullAllowed; std::string m_packExpression; // an expression to pack data into the stream + std::string m_paramCheckExpression; //an expression to check parameter value }; diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/gl_base_types.h b/tools/emulator/opengl/shared/OpenglCodecCommon/gl_base_types.h index 8a7ad58f0..d7bdef8bf 100644 --- a/tools/emulator/opengl/shared/OpenglCodecCommon/gl_base_types.h +++ b/tools/emulator/opengl/shared/OpenglCodecCommon/gl_base_types.h @@ -48,4 +48,15 @@ typedef char *GLstr; /* JR XXX Treating this as an in handle - is this correct? */ typedef void * GLeglImageOES; +/* ErrorCode */ +#ifndef GL_INVALID_ENUM +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +#endif + #endif diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp index ef1e4b8fe..653f71f1d 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp +++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp @@ -36,6 +36,18 @@ static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this poin return ret; \ } +GLenum GLEncoder::s_glGetError(void * self) +{ + GLEncoder *ctx = (GLEncoder *)self; + GLenum err = ctx->getError(); + if(err != GL_NO_ERROR) { + ctx->setError(GL_NO_ERROR); + return err; + } + + return ctx->m_glGetError_enc(self); + +} GLint * GLEncoder::getCompressedTextureFormats() { @@ -453,6 +465,7 @@ GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream) { m_initialized = false; m_state = NULL; + m_error = GL_NO_ERROR; m_num_compressedTextureFormats = 0; m_compressedTextureFormats = NULL; // overrides; @@ -481,6 +494,7 @@ GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream) m_glDrawElements_enc = set_glDrawElements(s_glDrawElements); set_glGetString(s_glGetString); set_glFinish(s_glFinish); + m_glGetError_enc = set_glGetError(s_glGetError); } diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h index 6275820dc..7471bfb38 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h +++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h @@ -34,16 +34,21 @@ public: void setInitialized(){ m_initialized = true; }; bool isInitialized(){ return m_initialized; }; + virtual void setError(GLenum error){ m_error = error; }; + virtual GLenum getError() { return m_error; }; + private: bool m_initialized; GLClientState *m_state; + GLenum m_error; FixedBuffer m_fixedBuffer; GLint *m_compressedTextureFormats; GLint m_num_compressedTextureFormats; GLint *getCompressedTextureFormats(); // original functions; + glGetError_client_proc_t m_glGetError_enc; glGetIntegerv_client_proc_t m_glGetIntegerv_enc; glGetFloatv_client_proc_t m_glGetFloatv_enc; glGetFixedv_client_proc_t m_glGetFixedv_enc; @@ -69,6 +74,7 @@ private: glFlush_client_proc_t m_glFlush_enc; // statics + static GLenum s_glGetError(void * self); static void s_glGetIntegerv(void *self, GLenum pname, GLint *ptr); static void s_glGetBooleanv(void *self, GLenum pname, GLboolean *ptr); static void s_glGetFloatv(void *self, GLenum pname, GLfloat *ptr); diff --git a/tools/emulator/opengl/system/GLESv1_enc/gl.attrib b/tools/emulator/opengl/system/GLESv1_enc/gl.attrib index d3d97fcc2..8c0308460 100644 --- a/tools/emulator/opengl/system/GLESv1_enc/gl.attrib +++ b/tools/emulator/opengl/system/GLESv1_enc/gl.attrib @@ -99,10 +99,12 @@ glCompressedTexSubImage2D #void glDeleteBuffers(GLsizei n, GLuint *buffers) glDeleteBuffers len buffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDeleteTextures(GLsizei n, GLuint *textures) glDeleteTextures len textures (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #this function is marked as unsupported - it shouldn't be called directly #instead it translated into - glDrawDirectElements and glDrawIndirectElements @@ -129,11 +131,13 @@ glGetBufferParameteriv glGenBuffers len buffers (n * sizeof(GLuint)) dir buffers out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenTextures(GLsizei n, GLuint *textures) glGenTextures len textures (n * sizeof(GLuint)) dir textures out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGetFixedv(GLenum pname, GLfixed *params) glGetFixedv @@ -465,11 +469,13 @@ glTexParameterxvOES glDeleteRenderbuffersOES dir renderbuffers in len renderbuffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenRenderbuffersOES(GLsizei n, GLuint *renderbuffers) glGenRenderbuffersOES dir renderbuffers in len renderbuffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint *params) glGetRenderbufferParameterivOES @@ -480,11 +486,13 @@ glGetRenderbufferParameterivOES glDeleteFramebuffersOES dir framebuffers in len framebuffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenFramebuffersOES(GLsizei n, GLuint *framebuffers) glGenFramebuffersOES dir framebuffers out len framebuffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint *params) glGetFramebufferAttachmentParameterivOES @@ -559,11 +567,13 @@ glGetTexGenxvOES glDeleteVertexArraysOES dir arrays in len arrays (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenVertexArraysOES(GLsizei n, GLuint *arrays) glGenVertexArraysOES dir arrays out len arrays (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments) glDiscardFramebufferEXT @@ -590,11 +600,13 @@ glMultiDrawElementsSUN glDeleteFencesNV dir fences in len fences (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenFencesNV(GLsizei n, GLuint *fences) glGenFencesNV dir fences in len fences (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) glGetFenceivNV diff --git a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp index 1d645914e..969c0c981 100644 --- a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp +++ b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.cpp @@ -11,6 +11,7 @@ GL2Encoder::GL2Encoder(IOStream *stream) : gl2_encoder_context_t(stream) { m_initialized = false; m_state = NULL; + m_error = GL_NO_ERROR; m_num_compressedTextureFormats = 0; m_compressedTextureFormats = NULL; //overrides @@ -31,6 +32,7 @@ GL2Encoder::GL2Encoder(IOStream *stream) : gl2_encoder_context_t(stream) m_glGetVertexAttribPointerv = set_glGetVertexAttribPointerv(s_glGetVertexAttribPointerv); set_glShaderSource(s_glShaderSource); set_glFinish(s_glFinish); + m_glGetError_enc = set_glGetError(s_glGetError); } GL2Encoder::~GL2Encoder() @@ -38,6 +40,19 @@ GL2Encoder::~GL2Encoder() delete m_compressedTextureFormats; } +GLenum GL2Encoder::s_glGetError(void * self) +{ + GL2Encoder *ctx = (GL2Encoder *)self; + GLenum err = ctx->getError(); + if(err != GL_NO_ERROR) { + ctx->setError(GL_NO_ERROR); + return err; + } + + return ctx->m_glGetError_enc(self); + +} + void GL2Encoder::s_glFlush(void *self) { GL2Encoder *ctx = (GL2Encoder *) self; diff --git a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h index 3365d0603..bbe5659a7 100644 --- a/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h +++ b/tools/emulator/opengl/system/GLESv2_enc/GL2Encoder.h @@ -37,10 +37,14 @@ public: void setInitialized(){ m_initialized = true; }; bool isInitialized(){ return m_initialized; }; + virtual void setError(GLenum error){ m_error = error; }; + virtual GLenum getError() { return m_error; }; + private: bool m_initialized; GLClientState *m_state; + GLenum m_error; GLint *m_compressedTextureFormats; GLint m_num_compressedTextureFormats; @@ -50,6 +54,9 @@ private: void sendVertexAttributes(GLint first, GLsizei count); + glGetError_client_proc_t m_glGetError_enc; + static GLenum s_glGetError(void * self); + glFlush_client_proc_t m_glFlush_enc; static void s_glFlush(void * self); diff --git a/tools/emulator/opengl/system/GLESv2_enc/gl2.attrib b/tools/emulator/opengl/system/GLESv2_enc/gl2.attrib index 118fe5841..3b37bd898 100644 --- a/tools/emulator/opengl/system/GLESv2_enc/gl2.attrib +++ b/tools/emulator/opengl/system/GLESv2_enc/gl2.attrib @@ -26,18 +26,22 @@ glCompressedTexSubImage2D #void glDeleteBuffers(GLsizei n, GLuint *buffers) glDeleteBuffers len buffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers) glDeleteFramebuffers len framebuffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers) glDeleteRenderbuffers len renderbuffers (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDeleteTextures(GLsizei n, GLuint *textures) glDeleteTextures len textures (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *indices) glDrawElements @@ -47,21 +51,25 @@ glDrawElements glGenBuffers len buffers (n * sizeof(GLuint)) dir buffers out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenFramebuffers(GLsizei n, GLuint *framebuffers) glGenFramebuffers len framebuffers (n * sizeof(GLuint)) dir framebuffers out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenRenderbuffers(GLsizei n, GLuint *renderbuffers) glGenRenderbuffers len renderbuffers (n * sizeof(GLuint)) dir renderbuffers out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenTextures(GLsizei n, GLuint *textures) glGenTextures len textures (n * sizeof(GLuint)) dir textures out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) glGetActiveAttrib @@ -330,11 +338,13 @@ glCompressedTexSubImage3DOES #void glDeleteVertexArraysOES(GLsizei n, GLuint *arrays) glDeleteVertexArraysOES len arrays (n * sizeof(GLuint)) + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glGenVertexArraysOES(GLsizei n, GLuint *arrays) glGenVertexArraysOES len arrays (n * sizeof(GLuint)) dir arrays out + param_check n if(n<0){ ctx->setError(GL_INVALID_VALUE); return; } #void glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, GLenum *attachments)