Related
Let's say I run a Linux and I have no desktop environment installed. I boot up my system and all I have is my shell.
Is it possible to compile a program that uses the OpenGL libraries or directly uses the GPU driver to draw to the screen?
As far as I could understand I would always need some kind of desktop environment that would provide me a window that I can draw on. To keep it
simple let's say I just want to draw a simple 2d shape like a triangle in the middle of the screen for example.
And if that's possible how can I do it and where can I read more about the topic? If I am able to draw directly over my terminal does this mean that I would be able to run my app on a system that has a desktop environment and still be able to see my triangle?
Is it possible to compile a program that uses the OpenGL libraries or directly uses the GPU driver to draw to the screen?
Yes. With the EGL API this has been formalized and works most well with NVidia GPUs and their proprietary drivers. NVidia has it described on their dev blog here https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/
Essentially the steps are:
Create a OpenGL context for a PBuffer
#include <EGL/egl.h>
static const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
static const int pbufferWidth = 9;
static const int pbufferHeight = 9;
static const EGLint pbufferAttribs[] = {
EGL_WIDTH, pbufferWidth,
EGL_HEIGHT, pbufferHeight,
EGL_NONE,
};
int main(int argc, char *argv[])
{
// 1. Initialize EGL
EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint major, minor;
eglInitialize(eglDpy, &major, &minor);
// 2. Select an appropriate configuration
EGLint numConfigs;
EGLConfig eglCfg;
eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);
// 3. Create a surface
EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg,
pbufferAttribs);
// 4. Bind the API
eglBindAPI(EGL_OPENGL_API);
// 5. Create a context and make it current
EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT,
NULL);
eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx);
// from now on use your OpenGL context
// 6. Terminate EGL when finished
eglTerminate(eglDpy);
return 0;
}
and then go about the rest as per usual. Or you can even ditch the PBuffer completely and just use OpenGL manages resources, i.e. render to framebuffer objects. For that end you can omit creating the surface and just make the context current.
Here's an example for using EGL without display, no EGL surface, with OpenGL managed framebuffer.
#include <GL/glew.h>
#include <GL/glut.h>
#include <EGL/egl.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
using namespace std;
namespace render
{
int width, height;
float aspect;
void init();
void display();
int const fbo_width = 512;
int const fbo_height = 512;
GLuint fb, color, depth;
void *dumpbuf;
int dumpbuf_fd;
};
static const EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
int main(int argc, char *argv[])
{
// 1. Initialize EGL
EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint major, minor;
eglInitialize(eglDpy, &major, &minor);
// 2. Select an appropriate configuration
EGLint numConfigs;
EGLConfig eglCfg;
eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);
// 3. Bind the API
eglBindAPI(EGL_OPENGL_API);
// 3. Create a context and make it current
EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT,
NULL);
eglMakeCurrent(eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, eglCtx);
glewInit();
// from now on use your OpenGL context
render::init();
render::display();
// 4. Terminate EGL when finished
eglTerminate(eglDpy);
return 0;
}
void CHECK_FRAMEBUFFER_STATUS()
{
GLenum status;
status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
/* choose different formats */
break;
default:
/* programming error; will fail on all hardware */
throw "Framebuffer Error";
}
}
namespace render
{
float const light_dir[]={1,1,1,0};
float const light_color[]={1,0.95,0.9,1};
void init()
{
glGenFramebuffers(1, &fb);
glGenTextures(1, &color);
glGenRenderbuffers(1, &depth);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D( GL_TEXTURE_2D,
0,
GL_RGB8,
fbo_width, fbo_height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbo_width, fbo_height);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
GLint red_bits, green_bits, blue_bits, alpha_bits;
glGetIntegerv(GL_RED_BITS, &red_bits);
glGetIntegerv(GL_GREEN_BITS, &green_bits);
glGetIntegerv(GL_BLUE_BITS, &blue_bits);
glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
fprintf(stderr, "FBO format R%dG%dB%dA%d\n",
(int)red_bits,
(int)green_bits,
(int)blue_bits,
(int)alpha_bits );
CHECK_FRAMEBUFFER_STATUS();
dumpbuf_fd = open("/tmp/fbodump.rgb", O_CREAT|O_SYNC|O_RDWR, S_IRUSR|S_IWUSR);
assert(-1 != dumpbuf_fd);
dumpbuf = malloc(fbo_width*fbo_height*3);
assert(dumpbuf);
}
void render()
{
static float a=0, b=0, c=0;
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glViewport(0,0,fbo_width, fbo_height);
glClearColor(0,0,0,0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_TRIANGLES);
glColor3f(1,0,0);
glVertex3f(1,0,0);
glColor3f(0,1,0);
glVertex3f(0,1,0);
glColor3f(0,0,1);
glVertex3f(0,0,1);
glEnd();
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0,0,fbo_width,fbo_height,GL_RGB,GL_UNSIGNED_BYTE,dumpbuf);
lseek(dumpbuf_fd, SEEK_SET, 0);
write(dumpbuf_fd, dumpbuf, fbo_width*fbo_height*3);
}
}
I'm trying to get started with OpenCL (Intel opencl-1.2-3.0.56860). I managed to install the OpenCL SDK from Intel under Ubuntu 12.05 (using "alien" to convert the rpm packages to *.deb packages). Now I try to get my first simple OpenCL program running... To run the program I need to use set the LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=/opt/intel/opencl/lib64/
My Problem is, that I always get the error "CL_DEVICE_NOT_AVAILABLE" when calling clCreateContext(...).
Here is my source code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <CL/cl.h>
#include <CL/cl_platform.h>
#include <string.h>
// Enable double precision values
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
// OpenCL kernel. Each work item takes care of one element of c
const char *kernelSource = "\n" \
"__kernel void vecAdd( __global double *a, \n" \
" __global double *b, \n" \
" __global double *c, \n" \
" const unsigned int n) \n" \
"{ \n" \
" //Get our global thread ID \n" \
" int id = get_global_id(0); \n" \
" \n" \
" //Make sure we do not go out of bounds \n" \
" if (id < n) \n" \
" c[id] = a[id] + b[id]; \n" \
"} \n" \
"\n" ;
const char* err2str(cl_int err) {
switch(err) {
case CL_SUCCESS: return "CL_SUCCESS";
case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM";
case CL_INVALID_VALUE: return "CL_INVALID_VALUE";
case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE";
case CL_INVALID_BINARY: return "CL_INVALID_BINARY";
case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS";
case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION";
case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE";
default: return "unknown";
}
}
void pfn_notify(const char *errinfo, const void *private_info, size_t cb, void *user_data)
{
fprintf(stderr, "OpenCL Error (via pfn_notify): %s\n", errinfo);
}
cl_platform_id GetIntelOCLPlatform()
{
cl_platform_id pPlatforms[10] = { 0 };
char pPlatformName[128] = { 0 };
cl_uint uiPlatformsCount = 0;
cl_int err = clGetPlatformIDs(10, pPlatforms, &uiPlatformsCount);
for (cl_uint ui = 0; ui < uiPlatformsCount; ++ui)
{
err = clGetPlatformInfo(pPlatforms[ui], CL_PLATFORM_NAME, 128 * sizeof(char), pPlatformName, NULL);
if ( err != CL_SUCCESS )
{
printf("ERROR: Failed to retreive platform vendor name.\n", ui);
return NULL;
}
if (!strcmp(pPlatformName, "Intel(R) OpenCL"))
return pPlatforms[ui];
}
return NULL;
}
int main( int argc, char* argv[] )
{
cl_platform_id cpPlatform; // OpenCL platform
cl_device_id device_id; // device ID
cl_context context; // context
cl_command_queue queue; // command queue
cl_program program; // program
cl_kernel kernel; // kernel
size_t cb;
cl_device_id devices[100];
cl_uint devices_n = 0;
cl_int err;
cl_platform_id intel_platform_id = GetIntelOCLPlatform();
if( intel_platform_id == NULL ) {
printf("ERROR: Failed to find Intel OpenCL platform.\n");
return -1;
}
// Get Device Info...
err = clGetDeviceIDs(intel_platform_id, CL_DEVICE_TYPE_ALL, 100, devices, &devices_n);
printf("ERR(clGetDeviceIDs) = %d\n", err);
printf("#DEVICES: %d\n", devices_n);
for (int i=0; i<devices_n; i++) {
char buffer[10240];
cl_uint buf_uint;
cl_ulong buf_ulong;
printf(" -- %d --\n", i);
err = clGetDeviceInfo(devices[i], CL_DEVICE_NAME, sizeof(buffer), buffer, NULL);
printf(" DEVICE_NAME = %s\n", buffer);
err = clGetDeviceInfo(devices[i], CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL);
printf(" DEVICE_VENDOR = %s\n", buffer);
err = clGetDeviceInfo(devices[i], CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL);
printf(" DEVICE_VERSION = %s\n", buffer);
err = clGetDeviceInfo(devices[i], CL_DRIVER_VERSION, sizeof(buffer), buffer, NULL);
printf(" DRIVER_VERSION = %s\n", buffer);
err = clGetDeviceInfo(devices[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buf_uint), &buf_uint, NULL);
printf(" DEVICE_MAX_COMPUTE_UNITS = %u\n", (unsigned int)buf_uint);
err = clGetDeviceInfo(devices[i], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buf_uint), &buf_uint, NULL);
printf(" DEVICE_MAX_CLOCK_FREQUENCY = %u\n", (unsigned int)buf_uint);
err = clGetDeviceInfo(devices[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buf_ulong), &buf_ulong, NULL);
printf(" DEVICE_GLOBAL_MEM_SIZE = %llu\n", (unsigned long long)buf_ulong);
}
context = clCreateContext(NULL, 1, devices, &pfn_notify, NULL, &err);
printf("ERR(clCreateContext) = %d [%s]\n", err, err2str(err));
// Create a context
cl_context_properties context_properties[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)intel_platform_id, (cl_context_properties)NULL };
// context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
context = clCreateContextFromType(context_properties, CL_DEVICE_TYPE_CPU, NULL, NULL, &err);
printf("ERR(clCreateContextFromType) = %d [%s]\n", err, err2str(err));
if (err != CL_SUCCESS) exit(0);
if (context == (cl_context)0) {
printf("Illegal context?");
exit(0);
}
return 0;
}
The Output is:
ERR(clGetDeviceIDs) = 0
#DEVICES: 1
-- 0 --
DEVICE_NAME = Intel(R) Core(TM)2 Duo CPU P7450 # 2.13GHz
DEVICE_VENDOR = Intel(R) Corporation
DEVICE_VERSION = OpenCL 1.2 (Build 56860)
DRIVER_VERSION = 1.2
DEVICE_MAX_COMPUTE_UNITS = 2
DEVICE_MAX_CLOCK_FREQUENCY = 2130
DEVICE_GLOBAL_MEM_SIZE = 3152510976
ERR(clCreateContext) = -2 [CL_DEVICE_NOT_AVAILABLE]
ERR(clCreateContextFromType) = -2 [CL_DEVICE_NOT_AVAILABLE]
Any Ideas how to solve that?
Regards,
Stefan
---- EDIT -----
The CPU has the sse4_1 flag (also: sse, sse2, sss3).
cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Duo CPU P7450 # 2.13GHz
stepping : 6
microcode : 0x60c
cpu MHz : 800.000
cache size : 3072 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 lahf_lm dtherm
bogomips : 4255.56
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
[ same for the other core]
Intel OpenCL CPU needs at least SSE 4.1. The Core 2 Duo only goes up to SSSE3.
http://software.intel.com/en-us/articles/opencl-sdk-frequently-asked-questions#14
Edit: some version of the Core 2 Duo support SSE 4.1
Here is the list of supported processors for the Intel OpenCL drivers
http://software.intel.com/en-us/articles/opencl-release-notes#2
Some versions of Core 2 are not supported. " All other versions of Intel® Core™ 2 processors are not supported"
You can use, for example, CPU-Z to find out what version of SSE you CPU supports.
Install the AMD OpenCL CPU driver. It only needs SSE2. On windows I installed the Radeon GPU drivers even though I did not have a AMD GPU. It still installed the AMD OpenCL CPU drivers and it did not conflict with the Nvidia drivers. I don't know on Linux. But now I can use Intel CPU, AMD CPU, and Nvidia GPU OpenCL drivers.
Recently I have tried using MSAA (multisample anti-aliasing) under Linux. The result was surprising: everything worked like a charm with Nvidia proprietary drivers, however with nouveau drivers it does not work. The strange thing about this is that glxingo says that GLX_ARB_multisample is supported and I am able to get the appropriate FBConfig with GLX_SAMPLE_BUFFERS set to 1 and GLX_SAMPLES set to 4 (or 8). But when it comes to rendering, the picture is as no anti-aliasing is applied. The problem exists in both my project and freeglut, so I will provide a small glut-based program that demonstarates the problem:
/*
* Test multisampling and polygon smoothing.
*
* Brian Paul
* 4 November 2002
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
static GLfloat Zrot = 0;
static GLboolean Anim = GL_TRUE;
static GLboolean HaveMultisample = GL_TRUE;
static GLboolean DoMultisample = GL_TRUE;
static void
PrintString(const char *s)
{
while (*s) {
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
s++;
}
}
static void
Polygon( GLint verts, GLfloat radius, GLfloat z )
{
int i;
for (i = 0; i < verts; i++) {
float a = (i * 2.0 * 3.14159) / verts;
float x = radius * cos(a);
float y = radius * sin(a);
glVertex3f(x, y, z);
}
}
static void
DrawObject( void )
{
glLineWidth(3.0);
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
Polygon(12, 1.2, 0);
glEnd();
glLineWidth(1.0);
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
Polygon(12, 1.1, 0);
glEnd();
glColor3f(1, 0, 0);
glBegin(GL_POLYGON);
Polygon(12, 0.4, 0.3);
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_POLYGON);
Polygon(12, 0.6, 0.2);
glEnd();
glColor3f(0, 0, 1);
glBegin(GL_POLYGON);
Polygon(12, 0.8, 0.1);
glEnd();
glColor3f(1, 1, 1);
glBegin(GL_POLYGON);
Polygon(12, 1.0, 0);
glEnd();
}
static void
Display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1, 1, 1);
if (HaveMultisample) {
glRasterPos2f(-3.1, -1.6);
if (DoMultisample)
PrintString("MULTISAMPLE");
else
PrintString("MULTISAMPLE (off)");
}
glRasterPos2f(-0.8, -1.6);
PrintString("No antialiasing");
glRasterPos2f(1.6, -1.6);
PrintString("GL_POLYGON_SMOOTH");
/* multisample */
if (HaveMultisample) {
glEnable(GL_DEPTH_TEST);
if (DoMultisample)
glEnable(GL_MULTISAMPLE_ARB);
glPushMatrix();
glTranslatef(-2.5, 0, 0);
glPushMatrix();
glRotatef(Zrot, 0, 0, 1);
DrawObject();
glPopMatrix();
glPopMatrix();
glDisable(GL_MULTISAMPLE_ARB);
glDisable(GL_DEPTH_TEST);
}
/* non-aa */
glEnable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(0, 0, 0);
glPushMatrix();
glRotatef(Zrot, 0, 0, 1);
DrawObject();
glPopMatrix();
glPopMatrix();
glDisable(GL_DEPTH_TEST);
/* polygon smooth */
glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glPushMatrix();
glTranslatef(2.5, 0, 0);
glPushMatrix();
glRotatef(Zrot, 0, 0, 1);
DrawObject();
glPopMatrix();
glPopMatrix();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
glDisable(GL_BLEND);
glutSwapBuffers();
}
static void
Reshape( int width, int height )
{
GLfloat ar = (float) width / (float) height;
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-2.0*ar, 2.0*ar, -2.0, 2.0, -1.0, 1.0);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
static void
Idle( void )
{
Zrot = 0.01 * glutGet(GLUT_ELAPSED_TIME);
glutPostRedisplay();
}
static void
Key( unsigned char key, int x, int y )
{
const GLfloat step = 1.0;
(void) x;
(void) y;
switch (key) {
case 'a':
Anim = !Anim;
if (Anim)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 'm':
DoMultisample = !DoMultisample;
break;
case 'z':
Zrot = (int) (Zrot - step);
break;
case 'Z':
Zrot = (int) (Zrot + step);
break;
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void
Init( void )
{
/* GLUT imposes the four samples/pixel requirement */
int s;
glGetIntegerv(GL_SAMPLES_ARB, &s);
if (!glutExtensionSupported("GL_ARB_multisample") || s < 1) {
printf("Warning: multisample antialiasing not supported.\n");
HaveMultisample = GL_FALSE;
}
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_SAMPLES_ARB = %d\n", s);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
glGetIntegerv(GL_MULTISAMPLE_ARB, &s);
printf("GL_MULTISAMPLE_ARB = %d\n", s);
}
int
main( int argc, char *argv[] )
{
glutInit( &argc, argv );
glutInitWindowPosition( 0, 0 );
glutInitWindowSize( 600, 300 );
glutInitDisplayMode( GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE |
GLUT_DEPTH | GLUT_MULTISAMPLE );
glutCreateWindow(argv[0]);
glutReshapeFunc( Reshape );
glutKeyboardFunc( Key );
glutDisplayFunc( Display );
if (Anim)
glutIdleFunc( Idle );
Init();
glutMainLoop();
return 0;
}
Here is glxinfo output (excluding the visuals info):
name of display: :0.0
display: :0 screen: 0
direct rendering: Yes
server glx vendor string: SGI
server glx version string: 1.4
server glx extensions:
GLX_ARB_multisample, GLX_EXT_import_context, GLX_EXT_texture_from_pixmap,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_MESA_copy_sub_buffer,
GLX_OML_swap_method, GLX_SGI_swap_control, GLX_SGIS_multisample,
GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, GLX_SGIX_visual_select_group,
GLX_INTEL_swap_event
client glx vendor string: Mesa Project and SGI
client glx version string: 1.4
client glx extensions:
GLX_ARB_create_context, GLX_ARB_create_context_profile,
GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_import_context,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_EXT_framebuffer_sRGB,
GLX_EXT_create_context_es2_profile, GLX_MESA_copy_sub_buffer,
GLX_MESA_multithread_makecurrent, GLX_MESA_swap_control,
GLX_OML_swap_method, GLX_OML_sync_control, GLX_SGI_make_current_read,
GLX_SGI_swap_control, GLX_SGI_video_sync, GLX_SGIS_multisample,
GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, GLX_SGIX_visual_select_group,
GLX_EXT_texture_from_pixmap, GLX_INTEL_swap_event
GLX version: 1.4
GLX extensions:
GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_import_context,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_MESA_copy_sub_buffer,
GLX_MESA_multithread_makecurrent, GLX_MESA_swap_control,
GLX_OML_swap_method, GLX_OML_sync_control, GLX_SGI_make_current_read,
GLX_SGI_swap_control, GLX_SGI_video_sync, GLX_SGIS_multisample,
GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, GLX_SGIX_visual_select_group,
GLX_EXT_texture_from_pixmap
OpenGL vendor string: nouveau
OpenGL renderer string: Gallium 0.4 on NVC1
OpenGL version string: 2.1 Mesa 8.0.4
OpenGL shading language version string: 1.30
OpenGL extensions:
GL_ARB_multisample, GL_EXT_abgr, GL_EXT_bgra, GL_EXT_blend_color,
GL_EXT_blend_minmax, GL_EXT_blend_subtract, GL_EXT_copy_texture,
GL_EXT_polygon_offset, GL_EXT_subtexture, GL_EXT_texture_object,
GL_EXT_vertex_array, GL_EXT_compiled_vertex_array, GL_EXT_texture,
GL_EXT_texture3D, GL_IBM_rasterpos_clip, GL_ARB_point_parameters,
GL_EXT_draw_range_elements, GL_EXT_packed_pixels, GL_EXT_point_parameters,
GL_EXT_rescale_normal, GL_EXT_separate_specular_color,
GL_EXT_texture_edge_clamp, GL_SGIS_generate_mipmap,
GL_SGIS_texture_border_clamp, GL_SGIS_texture_edge_clamp,
GL_SGIS_texture_lod, GL_ARB_framebuffer_sRGB, GL_ARB_multitexture,
GL_EXT_framebuffer_sRGB, GL_IBM_multimode_draw_arrays,
GL_IBM_texture_mirrored_repeat, GL_ARB_texture_cube_map,
GL_ARB_texture_env_add, GL_ARB_transpose_matrix,
GL_EXT_blend_func_separate, GL_EXT_fog_coord, GL_EXT_multi_draw_arrays,
GL_EXT_secondary_color, GL_EXT_texture_env_add,
GL_EXT_texture_filter_anisotropic, GL_EXT_texture_lod_bias,
GL_INGR_blend_func_separate, GL_NV_blend_square, GL_NV_light_max_exponent,
GL_NV_texgen_reflection, GL_NV_texture_env_combine4,
GL_SUN_multi_draw_arrays, GL_ARB_texture_border_clamp,
GL_ARB_texture_compression, GL_EXT_framebuffer_object,
GL_EXT_texture_env_combine, GL_EXT_texture_env_dot3, GL_MESA_window_pos,
GL_NV_packed_depth_stencil, GL_NV_texture_rectangle, GL_ARB_depth_texture,
GL_ARB_occlusion_query, GL_ARB_shadow, GL_ARB_texture_env_combine,
GL_ARB_texture_env_crossbar, GL_ARB_texture_env_dot3,
GL_ARB_texture_mirrored_repeat, GL_ARB_window_pos,
GL_EXT_stencil_two_side, GL_EXT_texture_cube_map, GL_NV_depth_clamp,
GL_NV_fog_distance, GL_APPLE_packed_pixels, GL_APPLE_vertex_array_object,
GL_ARB_draw_buffers, GL_ARB_fragment_program, GL_ARB_fragment_shader,
GL_ARB_shader_objects, GL_ARB_vertex_program, GL_ARB_vertex_shader,
GL_ATI_draw_buffers, GL_ATI_texture_env_combine3, GL_EXT_shadow_funcs,
GL_EXT_stencil_wrap, GL_MESA_pack_invert, GL_NV_primitive_restart,
GL_ARB_depth_clamp, GL_ARB_fragment_program_shadow,
GL_ARB_half_float_pixel, GL_ARB_occlusion_query2, GL_ARB_point_sprite,
GL_ARB_shading_language_100, GL_ARB_sync, GL_ARB_texture_non_power_of_two,
GL_ARB_vertex_buffer_object, GL_ATI_blend_equation_separate,
GL_EXT_blend_equation_separate, GL_OES_read_format,
GL_ARB_color_buffer_float, GL_ARB_pixel_buffer_object,
GL_ARB_texture_compression_rgtc, GL_ARB_texture_rectangle,
GL_ATI_texture_compression_3dc, GL_EXT_packed_float,
GL_EXT_pixel_buffer_object, GL_EXT_texture_compression_rgtc,
GL_EXT_texture_mirror_clamp, GL_EXT_texture_rectangle,
GL_EXT_texture_sRGB, GL_EXT_texture_shared_exponent,
GL_ARB_framebuffer_object, GL_EXT_framebuffer_blit,
GL_EXT_framebuffer_multisample, GL_EXT_packed_depth_stencil,
GL_ARB_vertex_array_object, GL_ATI_separate_stencil,
GL_ATI_texture_mirror_once, GL_EXT_draw_buffers2, GL_EXT_draw_instanced,
GL_EXT_gpu_program_parameters, GL_EXT_texture_array,
GL_EXT_texture_compression_latc, GL_EXT_texture_integer,
GL_EXT_texture_sRGB_decode, GL_EXT_timer_query, GL_OES_EGL_image,
GL_MESA_texture_array, GL_ARB_copy_buffer, GL_ARB_depth_buffer_float,
GL_ARB_draw_instanced, GL_ARB_half_float_vertex, GL_ARB_instanced_arrays,
GL_ARB_map_buffer_range, GL_ARB_texture_rg, GL_ARB_texture_swizzle,
GL_ARB_vertex_array_bgra, GL_EXT_separate_shader_objects,
GL_EXT_texture_swizzle, GL_EXT_vertex_array_bgra,
GL_NV_conditional_render, GL_AMD_conservative_depth,
GL_AMD_draw_buffers_blend, GL_ARB_ES2_compatibility,
GL_ARB_draw_buffers_blend, GL_ARB_draw_elements_base_vertex,
GL_ARB_explicit_attrib_location, GL_ARB_fragment_coord_conventions,
GL_ARB_provoking_vertex, GL_ARB_sampler_objects, GL_ARB_seamless_cube_map,
GL_ARB_shader_texture_lod, GL_EXT_provoking_vertex, GL_EXT_texture_snorm,
GL_MESA_texture_signed_rgba, GL_NV_texture_barrier, GL_ARB_robustness,
GL_ARB_transform_feedback2, GL_ARB_conservative_depth,
GL_ARB_texture_storage, GL_EXT_transform_feedback
glewIsSupported says the extension is available, glGetIntegerv says the number of samples is 4, as specified when getting the FBConfig.
I have no idea of what is going on.
Edit: Here is the output of glXQueryExtensionsString:
GLX_ARB_get_proc_address GLX_ARB_multisample GLX_EXT_import_context GLX_EXT_visual_info GLX_EXT_visual_rating GLX_MESA_copy_sub_buffer GLX_MESA_multithread_makecurrent GLX_MESA_swap_control GLX_OML_swap_method GLX_OML_sync_control GLX_SGI_make_current_read GLX_SGI_swap_control GLX_SGI_video_sync GLX_SGIS_multisample GLX_SGIX_fbconfig GLX_SGIX_pbuffer GLX_SGIX_visual_select_group GLX_EXT_texture_from_pixmap
FORGET ABOUT MSAA. On nouveau UNLESS you have very fresh MESA + kernel + X.org.
MSAA is requirement for OpenGL 3.0 and up. So it was not high on priority list, up until recently. You need Mesa 9.0 for that.
(If you want tips on what to do to get those needed software, pls post your hardware, and software - distro, kernel, mesa, xorg - versions).
I'm looking for a good source of GLES2 samples for C++ (or C) on x86 Linux with Xorg.
The samples I can find are all in Objective C for iOS, or Java for Android, or JavaScript for WebGL.
The Kronos web site has a "tutorials" section that contains two lines saying "our tutorials index will go here." Given that GLES2 is 5 years old, I don't have much hope on a sudden surge of content there.
I already know OpenGL pretty well. I'd just like some convenient source for copy-and-paste context set-up code, really. Where can I find something like that?
Mesa demos!
http://cgit.freedesktop.org/mesa/demos
http://cgit.freedesktop.org/mesa/demos/tree/src/egl/opengles2
http://cgit.freedesktop.org/mesa/demos/tree/src/egl/opengles2/es2tri.c
GLFW, Mesa, Ubuntu 16.04 AMD64
I'm not sure if GLUT supports GLES, but GLFW does, greatly simplifying window management.
sudo apt-get install libglfw3-dev libgles2-mesa-dev
gcc glfw_triangle.c -lGLESv2 -lglfw
Output:
Source:
#include <stdio.h>
#include <stdlib.h>
#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
static const GLuint WIDTH = 800;
static const GLuint HEIGHT = 600;
static const GLchar* vertex_shader_source =
"#version 100\n"
"attribute vec3 position;\n"
"void main() {\n"
" gl_Position = vec4(position, 1.0);\n"
"}\n";
static const GLchar* fragment_shader_source =
"#version 100\n"
"void main() {\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
static const GLfloat vertices[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
GLint common_get_shader_program(const char *vertex_shader_source, const char *fragment_shader_source) {
enum Consts {INFOLOG_LEN = 512};
GLchar infoLog[INFOLOG_LEN];
GLint fragment_shader;
GLint shader_program;
GLint success;
GLint vertex_shader;
/* Vertex shader */
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Fragment shader */
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Link shaders */
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return shader_program;
}
int main(void) {
GLuint shader_program, vbo;
GLint pos;
GLFWwindow* window;
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL);
glfwMakeContextCurrent(window);
printf("GL_VERSION : %s\n", glGetString(GL_VERSION) );
printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );
shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
pos = glGetAttribLocation(shader_program, "position");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, WIDTH, HEIGHT);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glEnableVertexAttribArray(pos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
glDeleteBuffers(1, &vbo);
glfwTerminate();
return EXIT_SUCCESS;
}
The key line lines of code are:
#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
GLFW_INCLUDE_ES2 is documented at: http://www.glfw.org/docs/latest/build_guide.html#build_macros and a quick look at the source shows that it forwards to GLES:
#elif defined(GLFW_INCLUDE_ES2)
#include <GLES2/gl2.h>
#if defined(GLFW_INCLUDE_GLEXT)
#include <GLES2/gl2ext.h>
#endif
This source seems to be is in the common subset of GLES and OpenGL (like much of GLES), and also compiles with -lGL if we remove the #define GLFW_INCLUDE_ES2.
If we add things which are not in GLES like immediate rendering glBegin, link fails as expected.
See also: How to develop OpenGL ES (GLES) 2.0 applications on Linux?
Credits: genpfult made the code much more correct.
ARM Mali OpenGL ES SDK
download from: http://malideveloper.arm.com/resources/sdks/opengl-es-sdk-for-linux/
open the documentation HTML on a browser
follow the "Quick Start Guide", it's simple
Contains several interesting open source examples + windowing system boilerplate (X11 + EGL).
The build system supports easy cross compilation for ARM / Mali SoCs, but I haven't tested that yet.
The key component included seems to be the "OpenGL ES Emulator" http://malideveloper.arm.com/resources/tools/opengl-es-emulator/ which "maps OpenGL ES 3.2 API calls to the OpenGL API". But that does not ship with source, only precompiled.
Uses a custom enterprisey EULA that appears to be permissive, but yeah, ask your lawyer.
Tested on SDK v2.4.4.
I would like to develop OpenGL ES 2.0 apps on my Ubuntu machine. I could not find any libraries/emulators that support GLES 2.0 yet. Any suggestions?
GLFW, Mesa, Ubuntu 16.04 AMD64
This was not easy to setup on Ubuntu 14.04, but now it just works.
sudo apt-get install libglfw3-dev libgles2-mesa-dev
gcc glfw_triangle.c -lGLESv2 -lglfw
Output:
glfw_triangle.c
#include <stdio.h>
#include <stdlib.h>
#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
static const GLuint WIDTH = 800;
static const GLuint HEIGHT = 600;
static const GLchar* vertex_shader_source =
"#version 100\n"
"attribute vec3 position;\n"
"void main() {\n"
" gl_Position = vec4(position, 1.0);\n"
"}\n";
static const GLchar* fragment_shader_source =
"#version 100\n"
"void main() {\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
static const GLfloat vertices[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
GLint common_get_shader_program(const char *vertex_shader_source, const char *fragment_shader_source) {
enum Consts {INFOLOG_LEN = 512};
GLchar infoLog[INFOLOG_LEN];
GLint fragment_shader;
GLint shader_program;
GLint success;
GLint vertex_shader;
/* Vertex shader */
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Fragment shader */
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Link shaders */
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return shader_program;
}
int main(void) {
GLuint shader_program, vbo;
GLint pos;
GLFWwindow* window;
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL);
glfwMakeContextCurrent(window);
printf("GL_VERSION : %s\n", glGetString(GL_VERSION) );
printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );
shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
pos = glGetAttribLocation(shader_program, "position");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, WIDTH, HEIGHT);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glEnableVertexAttribArray(pos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
glDeleteBuffers(1, &vbo);
glfwTerminate();
return EXIT_SUCCESS;
}
The key line lines of code are:
#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
GLFW_INCLUDE_ES2 is documented at: http://www.glfw.org/docs/latest/build_guide.html#build_macros and a quick look at the source shows that it forwards to GLES:
#elif defined(GLFW_INCLUDE_ES2)
#include <GLES2/gl2.h>
#if defined(GLFW_INCLUDE_GLEXT)
#include <GLES2/gl2ext.h>
#endif
This source seems to be written in the common subset of GLES and OpenGL (like much of GLES), and also compiles with -lGL if we remove the #define GLFW_INCLUDE_ES2.
If we add things which are not in GLES like immediate rendering glBegin, link fails as expected.
See also: https://askubuntu.com/questions/244133/how-do-i-get-egl-and-opengles-libraries-for-ubuntu-running-on-virtualbox
Credits: genpfult made the code much more correct.
ARM Mali OpenGL ES SDK
download from: http://malideveloper.arm.com/resources/sdks/opengl-es-sdk-for-linux/
open the documentation HTML on a browser
follow the "Quick Start Guide", it's simple
Contains several interesting open source examples + windowing system boilerplate (X11 + EGL).
The build system supports easy cross compilation for ARM / Mali SoCs, but I haven't tested that yet.
The key component included seems to be the "OpenGL ES Emulator" http://malideveloper.arm.com/resources/tools/opengl-es-emulator/ which "maps OpenGL ES 3.2 API calls to the OpenGL API". But that does not ship with source, only precompiled.
Uses a custom enterprisey EULA that appears to be permissive, but yeah, ask your lawyer.
Tested on SDK v2.4.4.
Mesa supports it. If you want to restrict yourself to OpenGL ES only then you'll need to build it into a separate directory and then add the appropriate include and library directories.
Update:
You can (still) use PowerVR SDK and now it supports Vulkan as well. Updated links:
PowerVR SDK page: https://www.imgtec.com/developers/powervr-sdk-tools/powervr-sdk/
Installers download page: https://www.imgtec.com/developers/powervr-sdk-tools/installers/
Github repo: https://github.com/powervr-graphics/Native_SDK
At the time of my original answer, PowerVR SDK was the most complete solution (Mesa gained full OpenGL ES 2.0 support with its 3.1 release according to its Wikipedia page).
Now, Mesa and Mali SDK can also be a choice. For detailed info on those, please refer to this detailed answer by Ciro Santilli 冠状病毒审查六四事件法轮功
Original Answer:
You can use POWERVR SDK to emulate Opengl es on your PC. You can download the SDK here. The archive provides the necessary steps to install the emulation libraries as a documentation file and includes tutorials and demo applications with source codes.
Develop to the OpenGL 2.0 standard, and don't use immediate mode or fixed function mode. Essentially your program will be ES 2.0 compliant.
you can generate a header that has only those functions that you really need. And with glfw you can create an opengl es context. So you can't accidently use functions that you do not want to use, because they won't be defined in this way. I found this that might help you here.
gl load from the unofficial opengl sdk