I am working on a C program to be compiled to WASM and display an image in the browser. The point of this program is to learn to set things up using EGL, and therefore I am not interested in any answers involving e.g. SDL, GLFW, etc.
This code works to clear the screen to blue (I've ommitted error checking to reduce size):
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "emscripten.h"
struct Environment
{
EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
EGLSurface surface;
};
static struct Environment g_env = {};
bool initGL(struct Environment* env)
{
env->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(env->display, &env->majorVersion, &env->minorVersion);
EGLint numConfigs = 0;
EGLint attribList[] =
{
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 1,
EGL_NONE
};
EGLConfig config;
eglChooseConfig(env->display, attribList, &config, 1, &numConfigs);
env->surface = eglCreateWindowSurface(env->display, config, 0, NULL);
static const EGLint contextAttribList[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
};
EGLContext context = eglCreateContext(env->display, config, EGL_NO_CONTEXT, contextAttribList);
eglMakeCurrent(env->display, env->surface, env->surface, context);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
return true;
}
void draw()
{
glViewport(0, 0, 300, 150);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(g_env.display, g_env.surface);
}
int main(int argc, char *argv[])
{
if (!initGL(&g_env))
{
return 1;
}
emscripten_set_main_loop(clearScreen, 0, 1);
return 0;
}
But as soon as I add the following after glClearColor(...), I no longer see a blue screen in the browser:
const GLuint vertex_shader = load_shader(GL_VERTEX_SHADER, VERTEX_SHADER);
const GLuint fragment_shader = load_shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
I suspect the shader code is not at all relevent to the problem, but just in case, here is the code for load_shader, taken from the OpenGL ES 2 book (error checking ommitted)
GLuint load_shader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader ( type );
// Load the shader source
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader
glCompileShader ( shader );
// Check the compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
return shader;
}
And the shaders themselves:
char VERTEX_SHADER[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
char FRAGMENT_SHADER[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"}
Here is how I compile:
EMSCRIPTEN_OPTS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s MODULARIZE=1
${EMCC} main_web.c -o hello.js ${EMSCRIPTEN_OPTS}
glGetError() is not returning an error code.
And here is my HTML:
<html>
<body>
<p id="output" />
<canvas id="canvas"></canvas>
<script type="application/javascript" src="hello.js"></script>
<script type="application/javascript">
Module({
canvas: (() => document.getElementById('canvas'))(),
print: (() => {
var element = document.getElementById('output');
return function(text) {
element.innerHTML += text + "<br>";
};
})()
})
</script>
</body>
</html>
Why do I stop clearing the screen when I just load the shaders?
The problem is with the HTML. When printing to stdout, the inline element was interefering with the block <canvas> element.
Problem solved by wrapping <p id="output"/> in a div.
Related
The code is building successfully but when I run the code I have the following error -
The following is a new check for GLUT 3.0; update your code.
GLUT: Fatal Error in D:\6th Sem\4. CG UCS505\EasyAlgo\Project1\Debug\Project1.exe: redisplay needed for window 1, but no display callback.
I've tried everything but am not able to figure it out, am new with open gl and vs. Thank you for your help.
Here is the .cpp file code -
source.cpp
#include <GL/glut.h>
#include <debug.hpp>
#include <config.hpp>
#include <blobs.hpp>
#include <fonts.hpp>
#include <draw.hpp>
#include <highlight.hpp>
#include <animation.hpp>
#include <unistd.h>
#include <iostream>
using namespace std;
unsigned short mainWindow, subWindow1, subWindow2;
void Init(float, float, float);
void Init(float, float, float, int, int);
void mainInit();
void display();
void onClick(int, int, int, int);
void keyPress(unsigned char, int, int);
int main(int argc, char** argv)
{
#ifdef DEBUG
mode = "InsertionSort";
b1.bv.resize(7, blobs());
int rad[7] = { 28,32,20,28,36,45,31 };
for (int p = 0; p < 7; p++)
b1.bv[p].radius = (float)rad[p];
b1.min = 20;
b1.max = 45;
#endif
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WindowWidth, WindowHeight);
std::string title = "AlgoLucidator " + AL_VERSION;
mainWindow = glutCreateWindow(title.c_str());
glutPositionWindow(WIN_POS_X, WIN_POS_Y);
mainInit();
glutMouseFunc(onClick);
glutKeyboardFunc(keyPress);
subWindow1 = glutCreateSubWindow(mainWindow, 0, 0, WindowWidth / 4, WindowHeight);
Init(0.80f, 0.80f, 0.60f);
glutKeyboardFunc(keyPress);
glutDisplayFunc(display);
subWindow2 = glutCreateSubWindow(mainWindow, WindowWidth / 4, 0, 3 * WindowWidth / 4, WindowHeight);
Init(0.65f, 0.75f, 0.70f);
std::string mainInstruct = "Press 1. InsertionSort 2. BubbleSort 3. Dijkstra";
printText(0, 0, 0, -(5 * mainInstruct.size()), 540, mainInstruct);
glutMouseFunc(onClick);
glutKeyboardFunc(keyPress);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void Init(float r, float g, float b)
{
int CurrWindowWidth = glutGet(GLUT_WINDOW_WIDTH);
int CurrWindowHeight = glutGet(GLUT_WINDOW_HEIGHT);
glClearColor(r, g, b, 1);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-CurrWindowWidth, CurrWindowWidth, -CurrWindowHeight, CurrWindowHeight);
drawTitle(CurrWindowWidth, CurrWindowHeight);
}
void Init(float r, float g, float b, int width, int height)
{
glClearColor(r, g, b, 1);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-width, width, -height, height);
drawTitle(width, height);
}
void mainInit()
{
int CurrWindowWidth = glutGet(GLUT_WINDOW_WIDTH);
int CurrWindowHeight = glutGet(GLUT_WINDOW_HEIGHT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, CurrWindowWidth, 0, CurrWindowHeight);
glClearColor(0, 0, 0, 0.80f);
glClear(GL_COLOR_BUFFER_BIT);
}
void display()
{
glFlush();
}
void onClick(int button, int state, int oldx, int oldy)
{}
void keyPress(unsigned char key, int x, int y)
{
int activeWindow = glutGetWindow();
switch (key)
{
case 13: if (b1.pushreq)
{
b1.bv.push_back(blobs((float)base_radius));
}
if (activeWindow != subWindow2)
glutSetWindow(subWindow2);
if (mode == "InsertionSort")
{
drawInsertionSort();
}
else if (mode == "BubbleSort")
{
drawBubbleSort();
}
break;
case 27: glutDestroyWindow(mainWindow); //Esc
break;
case 49: mode = "InsertionSort";
b1.reset();
glutSetWindow(subWindow2);
glutMouseFunc(onClick2);
Init2(0.65f, 0.75f, 0.70f);
drawTitle3(960, 640);
break;
case 50: mode = "BubbleSort";
glutSetWindow(subWindow2);
glutMouseFunc(onClick3);
glutIdleFunc(display);
Init3(0.65f, 0.75f, 0.70f);
drawTitle4(960, 640);
break;
default:;
}
}
The error message is pretty much exactly telling what's wrong and how to fix it (QFT):
The following is a new check for GLUT 3.0; update your code. GLUT: Fatal Error in (…) Project1.exe: redisplay needed for window 1, but no display callback.
For first window you create, window one, the one created with glutCreateWindow you don't specify a display callback:
mainWindow = glutCreateWindow(title.c_str());
glutPositionWindow(WIN_POS_X, WIN_POS_Y);
mainInit();
glutMouseFunc(onClick);
glutKeyboardFunc(keyPress);
/// <<<<<<<< something is missing here
subWindow1 = glutCreateSubWindow(mainWindow, 0, 0, WindowWidth / 4, WindowHeight);
Give that first window you create a display callback and the error will go away.
On a second note: Nothing of what's happening in the …Init functions is initialization at all. OpenGL is a state machine, and everything done in …Init is state prepration that ought to happen at the start of rendering a frame.
Finally I found that it's the issue of relative file path.
The fragment code file and the vertex code file are not found with my relative file path. So no code was sent to the shader.
I changed relative file path with absolute path, the project worked well.
--------------------------------Following are more details about my project---------------------------------------
Xcode version: 6.1 (6A1052c)
iOS version: OS X E Capitan 10.11.6 (15G31)
GFX card: Intel Iris 1536 MB
Code of vertex shader:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 1.0);
ourColor = color;
TexCoord = vec2( texCoord.x , 1.0 - texCoord.y );
}
Code of fragment shader:
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture1;
void main()
{
color = texture(ourTexture1,TexCoord ) * vec4(ourColor,1.0);
}
----------------------------------Following is my original question-----------------------------------------------
I met a problem with OpenGL programming, the console output is like this:
The log is empty.
I've checked my code for several times and I really didn't know what the cause could be.
So can anyone tell me what may the cause be ?
Following is my shader code:
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
class Shader
{
public:
GLuint Program;
// Constructor generates the shader on the fly
Shader( const GLchar *vertexPath, const GLchar *fragmentPath )
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions ( std::ifstream::badbit );
fShaderFile.exceptions ( std::ifstream::badbit );
try
{
// Open files
vShaderFile.open( vertexPath );
fShaderFile.open( fragmentPath );
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf( );
fShaderStream << fShaderFile.rdbuf( );
// close file handlers
vShaderFile.close( );
fShaderFile.close( );
// Convert stream into string
vertexCode = vShaderStream.str( );
fragmentCode = fShaderStream.str( );
}
catch ( std::ifstream::failure e )
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar *vShaderCode = vertexCode.c_str( );
const GLchar *fShaderCode = fragmentCode.c_str( );
// 2. Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertex, 1, &vShaderCode, NULL );
glCompileShader( vertex );
// Print compile errors if any
glGetShaderiv( vertex, GL_COMPILE_STATUS, &success );
std::cout <<"Vertex::" << success << std::endl;
if ( !success )
{
glGetShaderInfoLog( vertex, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment Shader
fragment = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragment, 1, &fShaderCode, NULL );
glCompileShader( fragment );
// Print compile errors if any
glGetShaderiv( fragment, GL_COMPILE_STATUS, &success );
std::cout <<"Fragment::" << success << std::endl;
if ( !success )
{
glGetShaderInfoLog( fragment, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader Program
this->Program = glCreateProgram( );
glAttachShader( this->Program, vertex );
glAttachShader( this->Program, fragment );
glLinkProgram( this->Program );
// Print linking errors if any
glGetProgramiv( this->Program, GL_LINK_STATUS, &success );
std::cout <<"linking::" << success << std::endl;
if (!success)
{
glGetProgramInfoLog( this->Program, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader( vertex );
glDeleteShader( fragment );
}
// Uses the current shader
void Use( )
{
glUseProgram( this->Program );
}
};
Finally I found that it's the issue of relative file path. The fragment code file and the vertex code file are not found with my relative file path. So no code was sent to the shader. I changed relative file path with absolute path, the project worked well.
i try to set simple texture:
fp:
uniform sampler2D colorMap;
out vec4 vFragColor;
smooth in vec2 vVaryingTexCoords;
void main(void)
{
vFragColor = texture(colorMap, vVaryingTexCoords.st);
}
vb:
#version 130
in vec4 vVertex;
in vec2 vTexCoords;
smooth out vec2 vVaryingTexCoords;
void main(void)
{
vVaryingTexCoords = vTexCoords;
gl_Position = vVertex;
}
here is a code to loading:
#ifdef linux
#include <cstdlib>
#endif
#ifdef __APPLE__
#if IPHONE
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#define OPENGL_ES
#else
//#include "GL/glew.h"
#import <OpenGL/glext.h>
#include <OpenGL/gl3.h> // Apple OpenGL haders (version depends on OS X SDK version)
#endif
#include <unistd.h>
#endif
GLuint gltLoadShaderPairWithAttributes(const char *szVertexProg, const char *szFragmentProg, ...)
{
// Temporary Shader objects
GLuint hVertexShader;
GLuint hFragmentShader;
GLuint hReturn = 0;
GLint testVal;
// Create shader objects
hVertexShader = glCreateShader(GL_VERTEX_SHADER);
hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// Load them. If fail clean up and return null
// Vertex Program
if(gltLoadShaderFile(szVertexProg, hVertexShader) == false)
{
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
fprintf(stderr, "The shader at %s could ot be found.\n", szVertexProg);
return (GLuint)NULL;
}
// Fragment Program
if(gltLoadShaderFile(szFragmentProg, hFragmentShader) == false)
{
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
fprintf(stderr,"The shader at %s could not be found.\n", szFragmentProg);
return (GLuint)NULL;
}
// Compile them both
glCompileShader(hVertexShader);
glCompileShader(hFragmentShader);
// Check for errors in vertex shader
glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal);
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetShaderInfoLog(hVertexShader, 1024, NULL, infoLog);
fprintf(stderr, "The shader at %s failed to compile with the following error:\n%s\n", szVertexProg, infoLog);
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
return (GLuint)NULL;
}
// Check for errors in fragment shader
glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal);
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetShaderInfoLog(hFragmentShader, 1024, NULL, infoLog);
fprintf(stderr, "The shader at %s failed to compile with the following error:\n%s\n", szFragmentProg, infoLog);
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
return (GLuint)NULL;
}
// Create the final program object, and attach the shaders
hReturn = glCreateProgram();
glAttachShader(hReturn, hVertexShader);
glAttachShader(hReturn, hFragmentShader);
// Now, we need to bind the attribute names to their specific locations
// List of attributes
va_list attributeList;
va_start(attributeList, szFragmentProg);
// Iterate over this argument list
char *szNextArg;
int iArgCount = va_arg(attributeList, int); // Number of attributes
for(int i = 0; i < iArgCount; i++)
{
int index = va_arg(attributeList, int);
szNextArg = va_arg(attributeList, char*);
glBindAttribLocation(hReturn, index, szNextArg);
}
va_end(attributeList);
// Attempt to link
glLinkProgram(hReturn);
// These are no longer needed
glDeleteShader(hVertexShader);
glDeleteShader(hFragmentShader);
// Make sure link worked too
glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal);
if(testVal == GL_FALSE)
{
char infoLog[1024];
glGetProgramInfoLog(hReturn, 1024, NULL, infoLog);
fprintf(stderr,"The programs %s and %s failed to link with the following errors:\n%s\n",
szVertexProg, szFragmentProg, infoLog);
glDeleteProgram(hReturn);
return (GLuint)NULL;
}
// All done, return our ready to use shader program
return hReturn;
}
here is a output:
ERROR: 0:5: '' : version '130' is not supported
ERROR: 0:10: 'smooth' : syntax error syntax error
Where i'm wrong. I'm on last osx version, it's must supporting 1.5 GLSL and 3.2 gl follow official OpenGL description:
https://developer.apple.com/graphicsimaging/opengl/capabilities/index.html
but when i check by OpenGL extention viewer, it's looks like 1.2 version only supported. Do i need any backdoor ways to enable glsl 1.3 supporting?
OpenGL version 3.2 is only required to be able to compile GLSL version 1.40 and 1.50. While on Windows, most OpenGL implementations will accept a wide variety of shading language versions, on MacOSX, you're going to have to stick with what's required.
I'm trying to run an example GLUT program, but it only creates a white window and then freezes the application. I found it freezes when calling glutMainLoop (same if I call glutCheckLoop in a loop). Something I may be missing?
Here's the the sample code I found:
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Question 1: In a GLUT program, how is control passed
// back to the programmer? How is this set up during
// initialization?
int win_width = 512;
int win_height = 512;
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glutSwapBuffers();
}
void reshape( int w, int h )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// Question 3: What do the calls to glOrtho()
// and glViewport() accomplish?
glOrtho( 0., 1., 0., 1., -1., 1. );
glViewport( 0, 0, w, h );
win_width = w;
win_height = h;
glutPostRedisplay();
}
void keyboard( unsigned char key, int x, int y ) {
switch(key) {
case 27: // Escape key
exit(0);
break;
}
}
int main (int argc, char *argv[]) {
glutInit( &argc, argv );
// Question 2: What does the parameter to glutInitDisplayMode()
// specify?
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( win_width, win_height );
glutCreateWindow( "Intro Graphics Assignment 1" );
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutMainLoop();
return 0;
}
int main is not where you want glutMainLoop(), mate.
You should have that in your init method ie initGlutDisplay().
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Question 1: In a GLUT program, how is control passed
// back to the programmer? How is this set up during
// initialization?
int win_width = 512;
int win_height = 512;
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glutSwapBuffers();
}
void reshape( int w, int h )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// Question 3: What do the calls to glOrtho()
// and glViewport() accomplish?
glOrtho( 0., 1., 0., 1., -1., 1. );
glViewport( 0, 0, w, h );
win_width = w;
win_height = h;
glutPostRedisplay();
}
void keyboard( unsigned char key, int x, int y ) {
switch(key) {
case 27: // Escape key
exit(0);
break;
}
}
int initGlutDisplay(int argc, char* argv[]){
glutInit( &argc, argv );
// Question 2: What does the parameter to glutInitDisplayMode()
// specify?
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( win_width, win_height );
glutCreateWindow( "Intro Graphics Assignment 1" );
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutMainLoop();
return 0;
}
int main (int argc, char *argv[]) {
int win_width = 512;
int win_height = 512;
initGlutDisplay(argc, argv);
}
The above code should work perfectly.
EDIT
According to opengl
AGL is the old Carbon-based API with C bindings. The Carbon part
needed for windowing and event handling are not thread-safe. There is
no 64 bit version of this API.
I wonder if this is your issue. I would review the opengl Programming guide by apple to see if you missed any steps that might solve your problem.
It was a bug in the compiler (works now with gcc)
This is really architecture question or 'how does it work' question than a problem to solve.
Apple documentation claims that CGL is lowest level api for managing OpenGL contexts, yet is lacks functionality that allows to connect a context to a window.
AGL and Cocoa can bind a context to a window without a problem though, so the question is - how do they do that if they are built upon CGL?
The obvious way appears to be that they use CGL to render to offscreen memory and are then capable of compositing this somehow. If this is so, how does that happen?
There is a private function CGLSetSurface that connects a surface that is part of a window to a GL context created with CGLCreateContext. Both AGL and Cocoa use this function internally.
Complete example:
/*
mkdir -p build/test.app/Contents/MacOS
clang++ --std=c++11
-fno-exceptions
-fno-rtti
-mmacosx-version-min=10.9
-Wno-writable-strings
-Wno-deprecated-declarations
-framework OpenGL
-framework Carbon
-g gui8.cpp
-o build/test.app/Contents/MacOS/test
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <ApplicationServices/ApplicationServices.h>
#include <Carbon/Carbon.h>
#include <OpenGL/CGLTypes.h>
#include <OpenGL/CGLCurrent.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
typedef int CGSConnectionID;
typedef int CGSWindowID;
typedef int CGSSurfaceID;
typedef uint32_t _CGWindowID;
extern "C" {
typedef int CGSConnection;
typedef int CGSWindow;
typedef int CGSValue;
typedef enum _CGSWindowOrderingMode {
kCGSOrderAbove = 1, // Window is ordered above target.
kCGSOrderBelow = -1, // Window is ordered below target.
kCGSOrderOut = 0 // Window is removed from the on-screen window list.
} CGSWindowOrderingMode;
typedef void *CGSRegion;
typedef CGSRegion *CGSRegionRef;
typedef CGSWindow *CGSWindowRef;
extern CGError CGSNewWindow( CGSConnection cid, int, float, float, const CGSRegion, CGSWindowRef);
extern CGError CGSNewRegionWithRect( const CGRect * rect, CGSRegionRef newRegion );
extern OSStatus CGSOrderWindow(CGSConnection cid, CGSWindow win, CGSWindowOrderingMode place, CGSWindow relativeToWindow /* nullable */);
extern OSStatus CGSSetWindowProperty(const CGSConnection cid, CGSWindow wid, CGSValue key, CGSValue value);
extern CGSConnectionID CGSMainConnectionID(void);
extern CGError CGSAddSurface(CGSConnectionID cid, _CGWindowID wid, CGSSurfaceID *sid);
extern CGError CGSSetSurfaceBounds(CGSConnectionID cid, _CGWindowID wid, CGSSurfaceID sid, CGRect rect);
extern CGError CGSOrderSurface(CGSConnectionID cid, _CGWindowID wid, CGSSurfaceID sid, int a, int b);
extern OSStatus CGSMoveWindow(const CGSConnection cid, const CGSWindow wid, CGPoint *point);
extern CGLError CGLSetSurface(CGLContextObj gl, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid);
}
#define kCGSBufferedBackingType 2
int main () {
CGLContextObj cgl_context = NULL;
CGSWindow window = 0;
int width = 500, height = 500;
CGPoint window_pos = { .x = 200, .y = 200 };
bool quit = false;
CGSConnectionID connection_id = CGSMainConnectionID();
assert(connection_id);
{
CGSRegion region = NULL;
CGRect r = CGRectMake(0,0, width, height);
auto err1 = CGSNewRegionWithRect(&r, ®ion);
assert(region);
auto err2 = CGSNewWindow(connection_id, kCGSBufferedBackingType, window_pos.x, window_pos.y, region, &window);
assert(window);
auto err3 = CGSOrderWindow(connection_id, window, kCGSOrderAbove, 0);
assert (err3 == kCGErrorSuccess);
CGLPixelFormatAttribute attributes[] = {
kCGLPFADoubleBuffer,
kCGLPFAAccelerated, // Hardware rendering
// kCGLPFARendererID, (CGLPixelFormatAttribute) kCGLRendererGenericFloatID, // Software rendering
(CGLPixelFormatAttribute)0
};
CGLPixelFormatObj pix;
GLint num;
auto err4 = CGLChoosePixelFormat(attributes, &pix, &num);
assert(err4 == kCGLNoError); // CGLErrorString(err1)
assert(pix);
CGLCreateContext(pix, NULL, &cgl_context);
assert(cgl_context);
CGLDestroyPixelFormat(pix);
CGLSetCurrentContext(cgl_context);
GLint v_sync_enabled = 1;
CGLSetParameter(cgl_context, kCGLCPSwapInterval, &v_sync_enabled);
CGSSurfaceID surface_id = 0;
auto err5 = CGSAddSurface(connection_id, window, &surface_id);
assert(err5 == kCGErrorSuccess);
auto err6 = CGSSetSurfaceBounds(connection_id, window, surface_id, CGRectMake(0, 0, width, height));
assert(err6 == kCGErrorSuccess);
auto err7 = CGSOrderSurface(connection_id, window, surface_id, 1, 0);
assert(err7 == kCGErrorSuccess);
auto err8 = CGLSetSurface(cgl_context, connection_id, window, surface_id);
assert(err8 == kCGLNoError);
GLint drawable = 0;
CGLGetParameter(cgl_context, kCGLCPHasDrawable, &drawable);
assert(drawable == 1);
}
assert(glGetError() == GL_NO_ERROR);
CGPoint drag_starting_position;
bool drag_started = false;
while (!quit) {
glClearColor(1,1,0,1);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
static float a = 0;
glRotatef(a * 1000, 0, 0, 1);
// printf("a: %f\n", a);
a= a + .001;
glBegin(GL_QUADS);
if (a>1.5) a=0;
glColor4f(0,a,1,1);
glVertex2f(0.25, 0.25);
glVertex2f(0.75, 0.25);
glVertex2f(0.75, 0.75);
glVertex2f(0.25, 0.75);
glEnd();
auto err1 = CGLFlushDrawable(cgl_context);
assert(err1 == kCGLNoError);
assert(glGetError() == GL_NO_ERROR);
}
CGLSetCurrentContext(NULL);
CGLDestroyContext(cgl_context);
}
I didn't revisit the question ever since, this is what I was able to make out of it:
The undocumented api's that float around the net appear to be a missing block from all that - I was able to CGLSetSurface without it returning an error, however it didn't do all that much in the end. Apparently there is some other stuff that needs to be done to make everything work on such a low level.
In all, there doesn't appear to be a sane way to control everything through CGL. The way to handle everything is like everyone else is doing apparently - through Cocoa classes (using CGL for all the stuff other then attaching to window is fine though after that point).