*/
+#define glError() \
+{ \
+ /*const GLchar *err_file = strrchr(err_path, '/');*/ \
+ GLenum gl_error = glGetError(); \
+ \
+ /*++err_file;*/ \
+ \
+ for (; (gl_error); gl_error = glGetError()) \
+ fprintf(stderr, "%s: %d caught at line %u\n", \
+ __FUNCTION__, gl_error, __LINE__); \
+ /*(const GLchar*)gluErrorString(gl_error)*/ \
+}
+
+
+#define MAX_DEPTH 32
+
typedef struct {
Window id;
gint x, y, w, h;
+ gint depth;
gboolean input_only;
gboolean visible;
gint type; /* XXX make this an enum */
+ GLuint texname;
+ GLXPixmap glpixmap;
} LocoWindow;
typedef struct _LocoList {
} LocoList;
static Window loco_root;
+static Window loco_overlay;
/* Maps X Window ID -> LocoWindow* */
static GHashTable *window_map;
/* Maps X Window ID -> LocoList* which is in the stacking_top/bottom list */
/* From top to bottom */
static LocoList *stacking_top;
static LocoList *stacking_bottom;
+static VisualID visualIDs[MAX_DEPTH + 1];
+static XVisualInfo *glxPixmapVisuals[MAX_DEPTH + 1];
+static int loco_screen_num;
+
+void (*BindTexImageEXT)(Display *, GLXDrawable, int, const int *);
+void (*ReleaseTexImageEXT)(Display *, GLXDrawable, int);
/*
static void print_stacking()
}
*/
+int create_glxpixmap(LocoWindow *lw)
+{
+ XVisualInfo *visinfo;
+ Pixmap pixmap;
+ static const int attrs[] =
+ {
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+ None
+ };
+
+ static const int drawable_tfp_attrs[] =
+ {
+ GLX_CONFIG_CAVEAT, GLX_NONE,
+ GLX_DOUBLEBUFFER, False,
+ GLX_DEPTH_SIZE, 0,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_BIND_TO_TEXTURE_RGBA_EXT, True, // additional for tfp
+ None
+ };
+ int count;
+
+ pixmap = XCompositeNameWindowPixmap(obt_display, lw->id);
+ visinfo = glxPixmapVisuals[lw->depth];
+ if (!visinfo) {
+ printf("no visinfo for depth %d\n", lw->depth);
+ return 0;
+ }
+
+ GLXFBConfig fbc;
+ GLXFBConfig *fbconfigs = glXChooseFBConfig(obt_display,
+ loco_screen_num,
+ drawable_tfp_attrs, &count);
+
+ int i;
+ fbc = 0;
+ for(i = 0; i < count; ++i ) {
+ int value;
+ glXGetFBConfigAttrib(obt_display,
+ fbconfigs[i], GLX_VISUAL_ID, &value);
+ if(value == (int)visinfo->visualid)
+ {
+ fbc = fbconfigs[i];
+ XFree(fbconfigs);
+ }
+ }
+
+ if (!fbc) {
+ printf("fbconfigless\n");
+ return 0;
+ }
+
+ lw->glpixmap = glXCreatePixmap(obt_display, fbc, pixmap, attrs);
+}
+
+int bindPixmapToTexture(LocoWindow *lw)
+{
+ unsigned int target;
+ int success = 0;
+
+ if (lw->glpixmap == None) {
+ create_glxpixmap(lw);
+ }
+ if (lw->glpixmap == None)
+ return 0;
+/*
+ if (screen->queryDrawable (screen->display->display,
+ texture->pixmap,
+ GLX_TEXTURE_TARGET_EXT,
+ &target))
+ {
+ fprintf (stderr, "%s: glXQueryDrawable failed\n", programName);
+
+ glXDestroyGLXPixmap (screen->display->display, texture->pixmap);
+ texture->pixmap = None;
+
+ return FALSE;
+ }
+*/
+
+ glBindTexture(GL_TEXTURE_2D, lw->texname);
+glError();
+ BindTexImageEXT(obt_display, lw->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ return 1;
+}
+
+void destroy_glxpixmap(LocoWindow *lw)
+{
+ glXDestroyGLXPixmap(obt_display, lw->glpixmap);
+ lw->glpixmap = None;
+}
+
+
+void releasePixmapFromTexture (LocoWindow *lw)
+{
+ if (lw->glpixmap) {
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, lw->texname);
+
+ ReleaseTexImageEXT(obt_display, lw->glpixmap, GLX_FRONT_LEFT_EXT);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ }
+}
+
+static void full_composite(void)
+{
+ int ret;
+ LocoList *it;
+ glClear(GL_COLOR_BUFFER_BIT);
+ for (it = stacking_bottom; it != stacking_top; it = it->prev) {
+ if (!it->window->visible)
+ continue;
+ ret = bindPixmapToTexture(it->window);
+ glBegin(GL_QUADS);
+ glColor3f(1.0, 1.0, 1.0);
+ glVertex2i(it->window->x, it->window->y);
+ glTexCoord2f(1, 0);
+ glVertex2i(it->window->x + it->window->w, it->window->y);
+ glTexCoord2f(1, 1);
+ glVertex2i(it->window->x + it->window->w, it->window->y + it->window->h);
+ glTexCoord2f(0, 1);
+ glVertex2i(it->window->x, it->window->y + it->window->h);
+ glTexCoord2f(0, 0);
+ glEnd();
+ }
+ glXSwapBuffers(obt_display, loco_overlay);
+}
+
static LocoList* loco_list_prepend(LocoList **top, LocoList **bottom,
LocoWindow *window)
{
{
if (win->input_only) return;
- //XCompositeRedirectWindow(obt_display, win->id, CompositeRedirectAutomatic);
+ XCompositeRedirectWindow(obt_display, win->id, CompositeRedirectAutomatic);
/*something useful = */XDamageCreate(obt_display, win->id, XDamageReportRawRectangles);
}
lw->y = attrib.y;
lw->w = attrib.width;
lw->h = attrib.height;
+ lw->depth = attrib.depth;
+ lw->glpixmap = None;
+ glGenTextures(1, &lw->texname);
+ // glTexImage2D(TARGET, 0, GL_RGB, lw->w, lw->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
g_hash_table_insert(window_map, &lw->id, lw);
/* new windows are at the top */
it = loco_list_prepend(&stacking_top, &stacking_bottom, lw);
void COMPOSTER_RAWR(const XEvent *e, gpointer data)
{
+ int redraw_required = 0;
+
if (e->type == ConfigureNotify) {
LocoWindow *lw;
+redraw_required = 1;
printf("Window 0x%lx moved or something\n", e->xconfigure.window);
lw = find_window(e->xconfigure.window);
lw->x = e->xconfigure.x;
lw->y = e->xconfigure.y;
- lw->w = e->xconfigure.width;
- lw->h = e->xconfigure.height;
+ if ((lw->w != e->xconfigure.width) || (lw->h != e->xconfigure.height)) {
+ lw->w = e->xconfigure.width;
+ lw->h = e->xconfigure.height;
+ if (lw->glpixmap != None) {
+ destroy_glxpixmap(lw);
+ }
+ }
printf("Window 0x%lx above 0x%lx\n", pos->window->id,
above ? above->window->id : 0);
loco_list_move_before(&stacking_top, &stacking_bottom, pos, above);
LocoWindow *lw = find_window(e->xdestroywindow.window);
if (lw) {
hide_window(lw, TRUE);
+ if (lw->glpixmap != None) {
+ destroy_glxpixmap(lw);
+ }
remove_window(lw);
}
else
e->xunmap.window);
}
else if (e->type == obt_display_extension_damage_basep + XDamageNotify) {
+// LocoWindow *lw = find_window(e->xdamage.window);
+ // if (lw->visible)
+ redraw_required = 1;
}
+ if (redraw_required)
+ full_composite();
}
static void find_all_windows(gint screen)
void loco_set_mainloop(gint screen_num, ObtMainLoop *loop)
{
+ int db, stencil, depth;
+ int i, j, value, count;
int w, h;
- XVisualInfo *vi;
+ XVisualInfo *vi, tvis, *visinfo;
GLXContext cont;
int config[] =
{ GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, GLX_RGBA, None };
+ loco_screen_num = screen_num;
loco_root = obt_root(screen_num);
+ loco_overlay = XCompositeGetOverlayWindow(obt_display, loco_root);
+XserverRegion region = XFixesCreateRegion(obt_display, NULL, 0);
+
+ XFixesSetWindowShapeRegion (obt_display,
+ loco_overlay,
+ ShapeBounding,
+ 0, 0,
+ 0);
+ XFixesSetWindowShapeRegion (obt_display,
+ loco_overlay,
+ ShapeInput,
+ 0, 0,
+ region);
+
+ XFixesDestroyRegion (obt_display, region);
vi = glXChooseVisual(obt_display, screen_num, config);
cont = glXCreateContext(obt_display, vi, NULL, GL_TRUE);
if (cont == NULL)
printf("context creation failed\n");
- glXMakeCurrent(obt_display, loco_root, cont);
+ glXMakeCurrent(obt_display, loco_overlay, cont);
+
+ BindTexImageEXT = glXGetProcAddress("glXBindTexImageEXT");
+ ReleaseTexImageEXT = glXGetProcAddress("glXReleaseTexImageEXT");
w = WidthOfScreen(ScreenOfDisplay(obt_display, screen_num));
h = HeightOfScreen(ScreenOfDisplay(obt_display, screen_num));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glXSwapBuffers(obt_display, loco_root);
+ glEnable(GL_TEXTURE_2D);
+glError();
+ glXSwapBuffers(obt_display, loco_overlay);
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+// glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+// glEnable(GL_BLEND);
+ db = 32767;
+ stencil = 32767;
+ depth = 32767;
+ for (i = 0; i <= MAX_DEPTH; i++) {
+ tvis.depth = i;
+ visualIDs[i] = 0;
+ visinfo = XGetVisualInfo(obt_display, VisualDepthMask, &tvis, &count);
+ for (j = 0; j < count; j++) {
+ glXGetConfig(obt_display, &visinfo[j], GLX_USE_GL, &value);
+ if (!value)
+ continue;
+
+ glXGetConfig(obt_display, &visinfo[j], GLX_DOUBLEBUFFER, &value);
+ if (value > db)
+ continue;
+ db = value;
+
+ glXGetConfig(obt_display, &visinfo[j], GLX_STENCIL_SIZE, &value);
+ if (value > stencil)
+ continue;
+ stencil = value;
+
+ glXGetConfig(obt_display, &visinfo[j], GLX_DEPTH_SIZE, &value);
+ if (value > depth)
+ continue;
+ depth = value;
+
+ visualIDs[i] = visinfo[j].visualid;
+ }
+ }
+
+ for (i = 0 ;i <= MAX_DEPTH; i++) {
+ tvis.visualid = visualIDs[i];
+ glxPixmapVisuals[i] = XGetVisualInfo(obt_display, VisualIDMask, &tvis, &count);
+ if (glxPixmapVisuals[i])
+ printf("supporting depth %d\n", i);
+ }
obt_main_loop_x_add(loop, COMPOSTER_RAWR, NULL, NULL);
window_map = g_hash_table_new((GHashFunc)window_hash,
(GEqualFunc)window_comp);