swayfx-mosaic/tooling/probes/step20c-corec-v2/gpu/test_gl.c

80 lines
5.5 KiB
C

#define _GNU_SOURCE
#include "g2_gl.h"
#include <assert.h>
#include <limits.h>
#include <sys/resource.h>
#include <sys/prctl.h>
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<s.bytes;n++)assert(s.pixels[n]==0);}
if(i==1||i==2||i==5||i==6||i==7||i==8||i==9||i==10||i==12||i==13||i==14||i==15||i==16)assert(!read_calls);
if(i==8)assert(s.pre.exhausted&&s.pre.count==G2_ERRORS);
printf("PASS exact g2_read mode=%d reason=%s\n",i,s.reason);free(s.pixels);
}
size_t n=0;assert(!g2_size(INT_MAX,INT_MAX,0,&n));assert(!g2_size(2,3,G2_CAP-23,&n));assert(!g2_size(-1,3,0,&n));
assert(g2_size(2,3,G2_CAP-24,&n)&&n==24);
reset(0);struct g2_sample s=g2_read(99,INT_MAX,INT_MAX,0);assert(!s.success&&!read_calls);free(s.pixels);
puts("PASS size/overflow/exact-cap; black RGBA alpha zero is valid, no sentinel gate");return 0;
}