mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-common
synced 2025-12-26 22:55:35 +00:00
255 lines
6.6 KiB
C
255 lines
6.6 KiB
C
/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; 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);
|
|
}
|
|
|