blob: 771daed68b1e341177b9b8c9023490db667bf00f [file] [log] [blame]
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <stdio.h>
#include <string.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <EGL/egl.h>
#include <GL/gl.h>
#include "egl_init.h"
Display* g_x_display = NULL;
struct egl_state_t egl_create_state_window(int x, int y, int w, int h) {
return egl_create_state_window_shared(EGL_NO_CONTEXT, x, y, w, h);
}
struct egl_state_t egl_create_state_window_shared(EGLContext share_context,
int x, int y, int w, int h) {
struct egl_state_t retval;
retval.x_window_ = 0;
retval.x_pixmap_ = 0;
retval.display_ = EGL_NO_DISPLAY;
retval.surface_ = EGL_NO_SURFACE;
retval.context_ = EGL_NO_CONTEXT;
if (g_x_display == NULL) {
fprintf(stdout, "Using display: %s\n", XDisplayName(NULL));
g_x_display = XOpenDisplay(NULL);
if (g_x_display == NULL)
{
fprintf(stderr, "XOpenDisplay() failed.\n");
goto error;
}
}
Window x_root_window = DefaultRootWindow(g_x_display);
XSetWindowAttributes x_swa;
memset(&x_swa, 0, sizeof(x_swa));
x_swa.background_pixmap = None;
retval.x_window_ = XCreateWindow(g_x_display, x_root_window, x, y, w, h, 0,
CopyFromParent, InputOutput, CopyFromParent,
CWBackPixmap, &x_swa);
if (retval.x_window_ == 0) {
fprintf(stderr, "XCreateWindow() failed.\n");
goto error;
}
XMapWindow(g_x_display, retval.x_window_);
retval.display_ = eglGetDisplay(g_x_display);
if (retval.display_ == EGL_NO_DISPLAY) {
fprintf(stderr, "eglGetDisplay() failed.\n");
goto error;
}
if (!eglInitialize(retval.display_, NULL, NULL)) {
fprintf(stderr, "eglInitialize() failed with error: %x\n", eglGetError());
goto error;
}
static const EGLint config_attribs[] = {
EGL_BUFFER_SIZE, 24,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_NONE
};
EGLint num_configs;
if (!eglChooseConfig(retval.display_, config_attribs, NULL, 0,
&num_configs)) {
fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
goto error;
}
EGLConfig egl_config;
if (!eglChooseConfig(retval.display_, config_attribs, &egl_config, 1,
&num_configs)) {
fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
goto error;
}
retval.surface_ = eglCreateWindowSurface(retval.display_, egl_config,
retval.x_window_, NULL);
if (retval.surface_ == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreateWindowSurface() failed with error: %x\n",
eglGetError());
goto error;
}
static const EGLint context_attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
retval.context_ = eglCreateContext(retval.display_, egl_config,
share_context, context_attributes);
if (retval.context_ == EGL_NO_CONTEXT) {
fprintf(stderr, "eglCreateContext() failed with error: %x\n",
eglGetError());
goto error;
}
return retval;
error:
egl_destroy_state(&retval);
return retval;
}
struct egl_state_t egl_create_state_pixmap(int w, int h) {
struct egl_state_t retval;
retval.x_window_ = 0;
retval.x_pixmap_ = 0;
retval.display_ = EGL_NO_DISPLAY;
retval.surface_ = EGL_NO_SURFACE;
retval.context_ = EGL_NO_CONTEXT;
if (g_x_display == NULL) {
fprintf(stdout, "Using display: %s\n", XDisplayName(NULL));
g_x_display = XOpenDisplay(NULL);
if (g_x_display == NULL)
{
fprintf(stderr, "XOpenDisplay() failed.\n");
goto error;
}
}
{
Window x_root_window = DefaultRootWindow(g_x_display);
Window root;
int x, y;
unsigned int w, h, b, d;
XGetGeometry(g_x_display, x_root_window, &root, &x, &y, &w, &h, &b, &d);
retval.x_pixmap_ = XCreatePixmap(g_x_display, x_root_window, w, h, d);
}
if (retval.x_pixmap_ == 0) {
fprintf(stderr, "XCreatePixmap() failed.\n");
goto error;
}
retval.display_ = eglGetDisplay(g_x_display);
if (retval.display_ == EGL_NO_DISPLAY) {
fprintf(stderr, "eglGetDisplay() failed.\n");
goto error;
}
if (!eglInitialize(retval.display_, NULL, NULL)) {
fprintf(stderr, "eglInitialize() failed with error: %x\n", eglGetError());
goto error;
}
static const EGLint config_attribs[] = {
EGL_BUFFER_SIZE, 24,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_NONE
};
EGLint num_configs;
if (!eglChooseConfig(retval.display_, config_attribs, NULL, 0,
&num_configs)) {
fprintf(stderr, "eglChooseConfig() failed with error: %x\n",
eglGetError());
goto error;
}
EGLConfig egl_config;
if (!eglChooseConfig(retval.display_, config_attribs, &egl_config, 1,
&num_configs)) {
fprintf(stderr, "eglChooseConfig() failed with error: %x\n",
eglGetError());
goto error;
}
retval.surface_ = eglCreatePixmapSurface(retval.display_, egl_config,
retval.x_pixmap_, NULL);
if (retval.surface_ == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreatePixmapSurface() failed with error: %x\n",
eglGetError());
goto error;
}
static const EGLint context_attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
retval.context_ = eglCreateContext(retval.display_, egl_config,
EGL_NO_CONTEXT, context_attributes);
if (retval.context_ == EGL_NO_CONTEXT) {
fprintf(stderr, "eglCreateContext() failed with error: %x\n",
eglGetError());
goto error;
}
return retval;
error:
egl_destroy_state(&retval);
return retval;
}
struct egl_state_t egl_create_state_pbuffer(int w, int h) {
return egl_create_state_pbuffer_shared(EGL_NO_CONTEXT, w, h);
}
struct egl_state_t egl_create_state_pbuffer_shared(EGLContext share_context,
int w, int h) {
struct egl_state_t retval;
retval.x_window_ = 0;
retval.x_pixmap_ = 0;
retval.display_ = EGL_NO_DISPLAY;
retval.surface_ = EGL_NO_SURFACE;
retval.context_ = EGL_NO_CONTEXT;
if (g_x_display == NULL) {
fprintf(stdout, "Using display: %s\n", XDisplayName(NULL));
g_x_display = XOpenDisplay(NULL);
if (g_x_display == NULL)
{
fprintf(stderr, "XOpenDisplay() failed.\n");
goto error;
}
}
retval.display_ = eglGetDisplay(g_x_display);
if (retval.display_ == EGL_NO_DISPLAY) {
fprintf(stderr, "eglGetDisplay() failed.\n");
goto error;
}
if (!eglInitialize(retval.display_, NULL, NULL)) {
fprintf(stderr, "eglInitialize() failed with error: %x\n", eglGetError());
goto error;
}
static const EGLint config_attribs[] = {
EGL_BUFFER_SIZE, 24,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
EGL_NONE
};
EGLint num_configs;
if (!eglChooseConfig(retval.display_, config_attribs, NULL, 0,
&num_configs)) {
fprintf(stderr, "eglChooseConfig() failed with error: %x\n",
eglGetError());
goto error;
}
EGLConfig egl_config;
if (!eglChooseConfig(retval.display_, config_attribs, &egl_config, 1,
&num_configs)) {
fprintf(stderr, "eglChooseConfig() failed with error: %x\n",
eglGetError());
goto error;
}
EGLint pbuffer_attribs[] = {
EGL_WIDTH, w,
EGL_HEIGHT, h,
EGL_NONE,
};
retval.surface_ = eglCreatePbufferSurface(retval.display_, egl_config,
pbuffer_attribs);
if (retval.surface_ == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreatePixmapSurface() failed with error: %x\n",
eglGetError());
goto error;
}
static const EGLint context_attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
retval.context_ = eglCreateContext(retval.display_, egl_config,
share_context, context_attributes);
if (retval.context_ == EGL_NO_CONTEXT) {
fprintf(stderr, "eglCreateContext() failed with error: %x\n",
eglGetError());
goto error;
}
return retval;
error:
egl_destroy_state(&retval);
return retval;
}
void egl_destroy_state(struct egl_state_t* state) {
if (state->context_ != EGL_NO_CONTEXT) {
eglDestroyContext(state->display_, state->context_);
state->context_ = EGL_NO_CONTEXT;
}
if (state->surface_ != EGL_NO_SURFACE) {
eglDestroySurface(state->display_, state->surface_);
state->surface_ = EGL_NO_SURFACE;
}
if (state->display_ != EGL_NO_DISPLAY) {
state->display_ = EGL_NO_DISPLAY;
}
if (state->x_pixmap_ != 0) {
XFreePixmap(g_x_display, state->x_pixmap_);
state->x_pixmap_ = 0;
}
if (state->x_window_ != 0) {
XDestroyWindow(g_x_display, state->x_window_);
state->x_window_ = 0;
}
}