#define _GNU_SOURCE #include "g2_gl.h" #include #include #include #include static struct g2_state state; static int mode, read_calls, unsupported, pending, query_count; static bool read_done; static const char *version="OpenGL ES 3.2 FakeGL"; static void reset(int m) { memset(&state,0,sizeof(state));state.read_fbo=11;state.draw_fbo=12;state.rbo=13; state.pack=8;state.pbo=15;state.row=32;state.skip_rows=2;state.skip_pixels=3; state.viewport[2]=2;state.viewport[3]=3;state.scissor[2]=2;state.scissor[3]=3; state.program=21;state.active=GL_TEXTURE0;state.texture=22; mode=m;read_calls=unsupported=pending=query_count=0;read_done=false; version=(m==6||m==14)?"OpenGL ES 2.0 FakeGL":"OpenGL ES 3.2 FakeGL"; } EGLContext EGLAPIENTRY eglGetCurrentContext(void) {return mode==5?EGL_NO_CONTEXT:(EGLContext)(uintptr_t)(mode==17&&read_done?7:5);} EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) {return (EGLDisplay)(uintptr_t)6;} EGLenum EGLAPIENTRY eglQueryAPI(void) {return mode==12?EGL_OPENGL_API:EGL_OPENGL_ES_API;} EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay d,EGLContext c,EGLint a,EGLint *v) {(void)d;(void)c;(void)a;*v=mode==6?2:3;return mode==13?EGL_FALSE:EGL_TRUE;} GLenum GL_APIENTRY glGetError(void) { if(mode==1 && query_count==0) {query_count++;return GL_INVALID_OPERATION;} if(mode==8)return GL_INVALID_OPERATION; if(pending){GLenum e=(GLenum)pending;pending=0;return e;}return GL_NO_ERROR; } const GLubyte *GL_APIENTRY glGetString(GLenum e) {(void)e;return (const GLubyte *)version;} void GL_APIENTRY glGetIntegerv(GLenum e,GLint *v) { if(mode==6)unsupported++; if(mode==2 && query_count++==0)pending=GL_INVALID_ENUM; switch(e) { #define FIELD(e,f) case e:*v=state.f;break case GL_READ_BUFFER:*v=mode==16?GL_NONE:GL_COLOR_ATTACHMENT0;break; FIELD(GL_READ_FRAMEBUFFER_BINDING,read_fbo);FIELD(GL_DRAW_FRAMEBUFFER_BINDING,draw_fbo); FIELD(GL_RENDERBUFFER_BINDING,rbo);FIELD(GL_PACK_ALIGNMENT,pack);FIELD(GL_PIXEL_PACK_BUFFER_BINDING,pbo); FIELD(GL_PACK_ROW_LENGTH,row);FIELD(GL_PACK_SKIP_ROWS,skip_rows);FIELD(GL_PACK_SKIP_PIXELS,skip_pixels); FIELD(GL_CURRENT_PROGRAM,program);FIELD(GL_ACTIVE_TEXTURE,active);FIELD(GL_TEXTURE_BINDING_2D,texture); case GL_VIEWPORT:memcpy(v,state.viewport,sizeof(state.viewport));break; case GL_SCISSOR_BOX:memcpy(v,state.scissor,sizeof(state.scissor));break; default:unsupported++;pending=GL_INVALID_ENUM;break; } } GLboolean GL_APIENTRY glIsEnabled(GLenum e) {(void)e;return state.scissor_on;} void GL_APIENTRY glBindFramebuffer(GLenum e,GLuint v) {if(e==GL_READ_FRAMEBUFFER)state.read_fbo=(GLint)v;else state.draw_fbo=(GLint)v;} void GL_APIENTRY glBindRenderbuffer(GLenum e,GLuint v) {(void)e;state.rbo=(GLint)v;} void GL_APIENTRY glBindBuffer(GLenum e,GLuint v) {(void)e;if(mode==11&&read_done&&v==15)pending=GL_INVALID_OPERATION;if(!(mode==4&&read_done))state.pbo=(GLint)v;} void GL_APIENTRY glPixelStorei(GLenum e,GLint v) { if(mode==9&&e==GL_PACK_ALIGNMENT&&v==1)pending=GL_INVALID_OPERATION; switch(e) {case GL_PACK_ALIGNMENT:state.pack=v;break;case GL_PACK_ROW_LENGTH:state.row=v;break; case GL_PACK_SKIP_ROWS:state.skip_rows=v;break;case GL_PACK_SKIP_PIXELS:state.skip_pixels=v;break;default:unsupported++;} } void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum t,GLenum a,GLenum e,GLint *v) { (void)t;(void)a;if(mode==10)pending=GL_INVALID_ENUM;*v=e==GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE?(mode==7?GL_TEXTURE:GL_RENDERBUFFER):e==GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME?44:0; } void GL_APIENTRY glGetRenderbufferParameteriv(GLenum t,GLenum e,GLint *v) { (void)t;*v=e==GL_RENDERBUFFER_WIDTH?2:e==GL_RENDERBUFFER_HEIGHT?3:e==GL_RENDERBUFFER_INTERNAL_FORMAT?GL_RGBA8:e==GL_RENDERBUFFER_SAMPLES?(mode==15?4:0):8; } GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum e) {(void)e;return GL_FRAMEBUFFER_COMPLETE;} void GL_APIENTRY glReadPixels(GLint x,GLint y,GLsizei w,GLsizei h,GLenum f,GLenum t,void *p) { (void)x;(void)y;assert(f==GL_RGBA&&t==GL_UNSIGNED_BYTE);assert(state.pbo==0&&state.pack==1&&state.row==0); read_calls++;read_done=true;if(mode==3)pending=GL_INVALID_OPERATION;else memset(p,0,(size_t)w*(size_t)h*4); } int main(void) { struct rlimit r={0,0};assert(!setrlimit(RLIMIT_CORE,&r));assert(!prctl(PR_SET_DUMPABLE,0)); const char *reasons[]={"READ_SUCCESS","PREEXISTING_GL_ERRORS","STATE_QUERY_ERROR","READ_GL_ERROR","RESTORE_FAILED","UNKNOWN_CONTEXT","GLES_STATE_NOT_SUPPORTED","TEXTURE_ATTACHMENT_DIMENSIONS_NOT_PROVEN","PREEXISTING_GL_ERRORS","PACK_QUERY_ERROR","ATTACHMENT_QUERY_ERROR","RESTORE_FAILED","UNKNOWN_CONTEXT","EGL_QUERY_FAILED","GLES_STATE_NOT_SUPPORTED","ATTACHMENT_UNSUPPORTED","ATTACHMENT_UNSUPPORTED","RESTORE_FAILED"}; for(int i=0;i<18;i++) { reset(i);struct g2_state before=state;struct g2_sample s=g2_read(99,2,3,0); assert(s.success==(i==0));assert(!strcmp(s.reason,reasons[i]));assert(!unsupported); if(i==0||i==3||i==7)assert(!memcmp(&state,&before,sizeof(state))); if(i==0){assert(read_calls==1&&s.bytes==24);for(size_t n=0;n