mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-27 19:54:38 +00:00
57 lines
3.5 KiB
C
57 lines
3.5 KiB
C
/* Tiny native CGL/IOSurface round-trip, with a rejected cross-thread bind. */
|
|
#include <OpenGL/OpenGL.h>
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include <IOSurface/IOSurface.h>
|
|
#include <pthread.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
extern CGLError CGLReadbackIOSurface(IOSurfaceRef);
|
|
static CGLContextObj owner;
|
|
static CGLPixelFormatObj format;
|
|
static IOSurfaceRef surface;
|
|
static void *worker(void *unused) {
|
|
CGLContextObj c=0;assert(CGLCreateContext(format,0,&c)==kCGLNoError);
|
|
assert(CGLSetCurrentContext(c)==kCGLNoError);
|
|
assert(glGetString(GL_VERSION));
|
|
assert(CGLSetCurrentContext(owner)==kCGLBadState && CGLGetCurrentContext()==c);
|
|
assert(CGLReadbackIOSurface(surface)==kCGLBadState && CGLGetCurrentContext()==c);
|
|
assert(CGLSetCurrentContext(0)==kCGLNoError);CGLReleaseContext(c);return 0;
|
|
}
|
|
int main(void) {
|
|
CGLPixelFormatAttribute attributes[]={kCGLPFAColorSize,32,kCGLPFAAlphaSize,8,0};
|
|
CGLPixelFormatAttribute core[]={kCGLPFAOpenGLProfile,0x3200,kCGLPFAColorSize,32,kCGLPFAAlphaSize,8,0};GLint screens=0;
|
|
assert(CGLChoosePixelFormat(getenv("M327_CGL_CORE")?core:attributes,&format,&screens)==kCGLNoError);
|
|
assert(CGLCreateContext(format,0,&owner)==kCGLNoError);
|
|
assert(CGLSetCurrentContext(owner)==kCGLNoError);
|
|
const char *renderer=(const char*)glGetString(GL_RENDERER);assert(renderer);
|
|
printf("CGL_RENDER renderer=%s\n",renderer);fflush(stdout);
|
|
int dims[]={8,8,4,32};const void *keys[]={kIOSurfaceWidth,kIOSurfaceHeight,kIOSurfaceBytesPerElement,kIOSurfaceBytesPerRow};
|
|
const void *values[4];for(int i=0;i<4;i++)values[i]=CFNumberCreate(0,kCFNumberIntType,&dims[i]);
|
|
CFDictionaryRef options=CFDictionaryCreate(0,keys,values,4,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
|
|
surface=IOSurfaceCreate(options);assert(surface);
|
|
unsigned char expected[256];for(int i=0;i<256;i+=4){expected[i]=33;expected[i+1]=55;expected[i+2]=77;expected[i+3]=255;}
|
|
memcpy(IOSurfaceGetBaseAddress(surface),expected,sizeof(expected));
|
|
GLuint texture;glGenTextures(1,&texture);glBindTexture(GL_TEXTURE_2D,texture);
|
|
assert(CGLTexImageIOSurface2D(owner,GL_TEXTURE_2D,GL_RGBA,8,8,GL_RGBA,GL_UNSIGNED_BYTE,surface,0)==kCGLNoError);
|
|
memset(IOSurfaceGetBaseAddress(surface),0,256);
|
|
assert(CGLReadbackIOSurface(surface)==kCGLNoError);
|
|
assert(!memcmp(IOSurfaceGetBaseAddress(surface),expected,sizeof(expected)));
|
|
/* More than the old 256-entry cache, while the display binding stays live. */
|
|
IOSurfaceRef extra[300];GLuint textures[300];glGenTextures(300,textures);
|
|
for(int i=0;i<300;i++) {
|
|
extra[i]=IOSurfaceCreate(options);assert(extra[i]);
|
|
glBindTexture(GL_TEXTURE_2D,textures[i]);
|
|
assert(CGLTexImageIOSurface2D(owner,GL_TEXTURE_2D,GL_RGBA,8,8,GL_RGBA,GL_UNSIGNED_BYTE,extra[i],0)==kCGLNoError);
|
|
}
|
|
memset(IOSurfaceGetBaseAddress(surface),0,256);
|
|
assert(CGLReadbackIOSurface(surface)==kCGLNoError);
|
|
assert(!memcmp(IOSurfaceGetBaseAddress(surface),expected,sizeof(expected)));
|
|
for(int i=0;i<300;i++)CFRelease(extra[i]);glDeleteTextures(300,textures);
|
|
pthread_t thread;assert(!pthread_create(&thread,0,worker,0));pthread_join(thread,0);
|
|
glDeleteTextures(1,&texture);CGLSetCurrentContext(0);CGLReleaseContext(owner);
|
|
assert(CGLReadbackIOSurface(surface)==kCGLBadValue);
|
|
CGLReleasePixelFormat(format);CFRelease(surface);CFRelease(options);for(int i=0;i<4;i++)CFRelease(values[i]);
|
|
printf("CGL_RENDER pixels=pass worker_api=pass cross_thread_rejected=pass destroyed_binding=pass live_bindings_over256=pass\n");return 0;
|
|
}
|