/* 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 . */ #include #include #include #include #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); }