summaryrefslogtreecommitdiffstats
path: root/common/ogl_ctx.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/ogl_ctx.c')
-rw-r--r--common/ogl_ctx.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/common/ogl_ctx.c b/common/ogl_ctx.c
new file mode 100644
index 00000000..6b175115
--- /dev/null
+++ b/common/ogl_ctx.c
@@ -0,0 +1,253 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+#include "ogl_ctx.h"
+
+
+#define PANIC(str) { \
+ printf("%s: panic: %s", __FUNCTION__, str); \
+ abort(); \
+}
+
+enum {
+ OGLCTX_TYPE_PBUF,
+ OGLCTX_TYPE_PIXMAP,
+};
+
+struct OGLCtx {
+ int type;
+ Display *x_display;
+ GLXContext glx_context;
+ GLXDrawable drawable;
+};
+
+typedef struct OGLPixmapCtx {
+ OGLCtx base;
+ Pixmap pixmap;
+} OGLPixmapCtx;
+
+
+
+const char *oglctx_type_str(OGLCtx *ctx)
+{
+ static const char *pbuf_str = "pbuf";
+ static const char *pixmap_str = "pixmap";
+ static const char *invalid_str = "invalid";
+
+ switch (ctx->type) {
+ case OGLCTX_TYPE_PBUF:
+ return pbuf_str;
+ case OGLCTX_TYPE_PIXMAP:
+ return pixmap_str;
+ default:
+ return invalid_str;
+ }
+}
+
+void oglctx_make_current(OGLCtx *ctx)
+{
+ if (!glXMakeCurrent(ctx->x_display, ctx->drawable, ctx->glx_context)) {
+ printf("%s: failed\n", __FUNCTION__);
+ }
+}
+
+OGLCtx *pbuf_create(int width, int heigth)
+{
+ OGLCtx *ctx;
+ Display *x_display;
+ int num_configs;
+ GLXFBConfig *fb_config;
+ GLXPbuffer glx_pbuf;
+ GLXContext glx_context;
+
+ const int glx_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_STENCIL_SIZE, 4,
+ 0 };
+
+ int pbuf_attrib[] = { GLX_PRESERVED_CONTENTS, True,
+ GLX_PBUFFER_WIDTH, width,
+ GLX_PBUFFER_HEIGHT, heigth,
+ GLX_LARGEST_PBUFFER, False,
+ 0, 0 };
+
+ if (!(ctx = calloc(1, sizeof(*ctx)))) {
+ printf("%s: alloc pbuf failed\n", __FUNCTION__);
+ return NULL;
+ }
+
+ if (!(x_display = XOpenDisplay(NULL))) {
+ printf("%s: open display failed\n", __FUNCTION__);
+ goto error_1;
+ }
+
+ if (!(fb_config = glXChooseFBConfig(x_display, 0, glx_attributes, &num_configs)) ||
+ !num_configs) {
+ printf("%s: choose fb config failed\n", __FUNCTION__);
+ goto error_2;
+ }
+
+ if (!(glx_pbuf = glXCreatePbuffer(x_display, fb_config[0], pbuf_attrib))) {
+ goto error_3;
+ }
+
+ if (!(glx_context = glXCreateNewContext(x_display, fb_config[0], GLX_RGBA_TYPE, NULL, True))) {
+ printf("%s: create context failed\n", __FUNCTION__);
+ goto error_4;
+ }
+
+ XFree(fb_config);
+
+ ctx->type = OGLCTX_TYPE_PBUF;
+ ctx->drawable = glx_pbuf;
+ ctx->glx_context = glx_context;
+ ctx->x_display = x_display;
+
+ return ctx;
+
+error_4:
+ glXDestroyPbuffer(x_display, glx_pbuf);
+
+error_3:
+ XFree(fb_config);
+
+error_2:
+ XCloseDisplay(x_display);
+
+error_1:
+ free(ctx);
+
+ return NULL;
+}
+
+OGLCtx *pixmap_create(int width, int heigth)
+{
+ Display *x_display;
+ int num_configs;
+ GLXFBConfig *fb_config;
+ GLXPixmap glx_pixmap;
+ GLXContext glx_context;
+ Pixmap pixmap;
+ int screen;
+ Window root_window;
+ OGLPixmapCtx *pix;
+
+ const int glx_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_STENCIL_SIZE, 4,
+ 0 };
+
+ if (!(pix = calloc(1, sizeof(*pix)))) {
+ printf("%s: alloc pix failed\n", __FUNCTION__);
+ return NULL;
+ }
+
+ if (!(x_display = XOpenDisplay(NULL))) {
+ printf("%s: open display failed\n", __FUNCTION__);
+ goto error_1;
+ }
+
+ screen = DefaultScreen(x_display);
+ root_window = RootWindow(x_display, screen);
+
+ if (!(fb_config = glXChooseFBConfig(x_display, 0, glx_attributes, &num_configs)) ||
+ !num_configs) {
+ printf("%s: choose fb config failed\n", __FUNCTION__);
+ goto error_2;
+ }
+
+ if (!(pixmap = XCreatePixmap(x_display, root_window, width, heigth, 32 /*use fb config*/))) {
+ printf("%s: create x pixmap failed\n", __FUNCTION__);
+ goto error_3;
+ }
+
+ if (!(glx_pixmap = glXCreatePixmap(x_display, fb_config[0], pixmap, NULL))) {
+ printf("%s: create glx pixmap failed\n", __FUNCTION__);
+ goto error_4;
+ }
+
+
+ if (!(glx_context = glXCreateNewContext(x_display, fb_config[0], GLX_RGBA_TYPE, NULL, True))) {
+ printf("%s: create context failed\n", __FUNCTION__);
+ goto error_5;
+ }
+
+ XFree(fb_config);
+
+ pix->base.type = OGLCTX_TYPE_PIXMAP;
+ pix->base.x_display = x_display;
+ pix->base.drawable = glx_pixmap;
+ pix->base.glx_context = glx_context;
+ pix->pixmap = pixmap;
+
+ return &pix->base;
+
+error_5:
+ glXDestroyPixmap(x_display, glx_pixmap);
+
+error_4:
+ XFreePixmap(x_display, pixmap);
+
+error_3:
+ XFree(fb_config);
+
+error_2:
+ XCloseDisplay(x_display);
+
+error_1:
+ free(pix);
+
+ return NULL;
+}
+
+void oglctx_destroy(OGLCtx *ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ // test is current ?
+
+ glXDestroyContext(ctx->x_display, ctx->glx_context);
+ switch (ctx->type) {
+ case OGLCTX_TYPE_PBUF:
+ glXDestroyPbuffer(ctx->x_display, ctx->drawable);
+ break;
+ case OGLCTX_TYPE_PIXMAP:
+ glXDestroyPixmap(ctx->x_display, ctx->drawable);
+ XFreePixmap(ctx->x_display, ((OGLPixmapCtx *)ctx)->pixmap);
+ break;
+ default:
+ PANIC("invalid ogl ctx type");
+ }
+
+ XCloseDisplay(ctx->x_display);
+ free(ctx);
+}
+