#include "pixmap_texture.h" #include bool ngxc_pixmap_texture_init(ngxc_pixmap_texture *window_texture, Display *display, Pixmap pixmap) { window_texture->display = display; window_texture->pixmap = pixmap; window_texture->glx_pixmap = None; window_texture->texture_id = 0; window_texture->width = 0; window_texture->height = 0; return ngxc_pixmap_texture_on_resize(window_texture); } static void ngxc_pixmap_texture_cleanup(ngxc_pixmap_texture *self, int delete_texture) { if(delete_texture && self->texture_id) { glDeleteTextures(1, &self->texture_id); self->texture_id = 0; } if(self->glx_pixmap) { glXDestroyPixmap(self->display, self->glx_pixmap); glXReleaseTexImageEXT(self->display, self->glx_pixmap, GLX_FRONT_EXT); self->glx_pixmap = None; } } void ngxc_pixmap_texture_deinit(ngxc_pixmap_texture *self) { ngxc_pixmap_texture_cleanup(self, 1); } bool ngxc_pixmap_texture_on_resize(ngxc_pixmap_texture *self) { ngxc_pixmap_texture_cleanup(self, 0); GLXFBConfig *configs = NULL; GLXPixmap glx_pixmap = None; GLuint texture_id = 0; int glx_pixmap_bound = 0; const int pixmap_config[] = { GLX_BIND_TO_TEXTURE_RGB_EXT, True, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT, GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, /*GLX_BIND_TO_MIPMAP_TEXTURE_EXT, True,*/ GLX_BUFFER_SIZE, 24, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 0, None }; const int pixmap_attribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, /*GLX_MIPMAP_TEXTURE_EXT, True,*/ None }; Window root_window; int x, y; unsigned int width = 0; unsigned int height = 0; unsigned int border_width; unsigned int depth = 32; if(!XGetGeometry(self->display, self->pixmap, &root_window, &x, &y, &width, &height, &border_width, &depth)) { fprintf(stderr, "Failed to get pixmap attributes\n"); return false; } GLXFBConfig config; int c; configs = glXChooseFBConfig(self->display, 0, pixmap_config, &c); if(!configs) { fprintf(stderr, "Failed to choose fb config\n"); return false; } int found = 0; for (int i = 0; i < c; i++) { config = configs[i]; XVisualInfo *visual = glXGetVisualFromFBConfig(self->display, config); if(!visual) continue; if((int)depth != visual->depth) { XFree(visual); continue; } XFree(visual); found = 1; break; } if(!found) { fprintf(stderr, "No matching fb config found\n"); goto cleanup; } glx_pixmap = glXCreatePixmap(self->display, config, self->pixmap, pixmap_attribs); if(!glx_pixmap) { goto cleanup; } if(self->texture_id == 0) { glGenTextures(1, &texture_id); if(texture_id == 0) { goto cleanup; } glBindTexture(GL_TEXTURE_2D, texture_id); } else { glBindTexture(GL_TEXTURE_2D, self->texture_id); } glXBindTexImageEXT(self->display, glx_pixmap, GLX_FRONT_EXT, NULL); glx_pixmap_bound = 1; glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glBindTexture(GL_TEXTURE_2D, 0); self->width = width; self->height = height; XFree(configs); self->glx_pixmap = glx_pixmap; if(texture_id != 0) self->texture_id = texture_id; return true; cleanup: if(texture_id != 0) glDeleteTextures(1, &texture_id); if(glx_pixmap) glXDestroyPixmap(self->display, glx_pixmap); if(glx_pixmap_bound) glXReleaseTexImageEXT(self->display, glx_pixmap, GLX_FRONT_EXT); if(configs) XFree(configs); return false; }