added transparency, cleanup

This commit is contained in:
Jarcode
2018-01-07 18:35:40 -08:00
parent 847f26c5fb
commit 2e0d0921c5
7 changed files with 304 additions and 81 deletions

139
xwin.c
View File

@@ -7,10 +7,15 @@
#include <string.h>
#include <limits.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/XShm.h>
#define GLFW_EXPOSE_NATIVE_X11
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
@@ -77,3 +82,137 @@ void xwin_settype(struct renderer* rd, const char* type) {
XChangeProperty(d, w, wtype, XA_ATOM, 32, PropModeReplace, (unsigned char*) &desk, 1);
XCloseDisplay(d);
}
static Pixmap get_pixmap(Display* d, Window w) {
Pixmap p;
Atom act_type;
int act_format;
unsigned long nitems, bytes_after;
unsigned char *data = NULL;
Atom id;
id = XInternAtom(d, "_XROOTPMAP_ID", False);
if (XGetWindowProperty(d, w, id, 0, 1, False, XA_PIXMAP,
&act_type, &act_format, &nitems, &bytes_after,
&data) == Success) {
if (data) {
p = *((Pixmap *) data);
XFree(data);
}
}
return p;
}
unsigned int xwin_copyglbg(struct renderer* rd, unsigned int tex) {
GLuint texture = (GLuint) tex;
if (!texture)
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLFWwindow* gwin = (GLFWwindow*) rd_get_impl_window(rd);
int x, y, w, h;
glfwGetFramebufferSize(gwin, &w, &h);
glfwGetWindowPos(gwin, &x, &y);
XColor c;
Display* d = XOpenDisplay(0);
Pixmap p = get_pixmap(d, RootWindow(d, DefaultScreen(d)));
/* Obtain section of root pixmap using XShm */
XShmSegmentInfo shminfo;
Visual* visual = DefaultVisual(d, DefaultScreen(d));
XVisualInfo match = { .visualid = XVisualIDFromVisual(visual) };
int nret;
XVisualInfo* info = XGetVisualInfo(d, VisualIDMask, &match, &nret);
XImage* image = XShmCreateImage(d, visual, info->depth, ZPixmap, NULL,
&shminfo, (unsigned int) w, (unsigned int) h);
shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT | 0777);
shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
shminfo.readOnly = false;
XShmAttach(d, &shminfo);
XShmGetImage(d, p, image, x, y, AllPlanes);
/* Try to convert pixel bit depth to OpenGL storage format. The following formats\
will need intermediate conversion before OpenGL can accept the data:
- 8-bit pixel formats (retro displays, low-bandwidth virtual displays)
- 36-bit pixel formats (rare deep color displays) */
bool invalid = false, aligned = false;
GLenum type;
switch (image->bits_per_pixel) {
case 16:
switch (image->depth) {
case 12: type = GL_UNSIGNED_SHORT_4_4_4_4; break; /* 12-bit (rare) */
case 15: type = GL_UNSIGNED_SHORT_5_5_5_1; break; /* 15-bit, hi-color */
case 16: /* 16-bit, hi-color */
type = GL_UNSIGNED_SHORT_5_6_5;
aligned = true;
break;
}
break;
case 32:
switch (image->depth) {
case 24: type = GL_UNSIGNED_BYTE; break; /* 24-bit, true color */
case 30: type = GL_UNSIGNED_INT_10_10_10_2; break; /* 30-bit, deep color */
}
break;
case 64:
if (image->depth == 48) /* 48-bit deep color */
type = GL_UNSIGNED_SHORT;
else goto invalid;
break;
/* >64-bit formats */
case 128:
if (image->depth == 96)
type = GL_UNSIGNED_INT;
else goto invalid;
break;
default:
invalid: invalid = true;
}
uint8_t* buf;
if (invalid) {
abort();
/* Manual reformat (slow) */
buf = malloc(4 * w * h);
int xi, yi;
Colormap map = DefaultColormap(d, DefaultScreen(d));
for (yi = 0; yi < h; ++yi) {
for (xi = 0; xi < w; ++xi) {
c.pixel = XGetPixel(image, xi, yi);
XQueryColor(d, map, &c);
size_t base = (xi + (yi * w)) * 4;
buf[base + 0] = c.red / 256;
buf[base + 1] = c.green / 256;
buf[base + 2] = c.blue / 256;
buf[base + 3] = 255;
}
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
free(buf);
} else {
/* Use image data directly. The alpha value is garbage/unassigned data, but
we need to read it because X11 keeps pixel data aligned */
buf = image->data;
/* Data could be 2, 4, or 8 byte aligned, the RGBA format and type (depth)
already ensures reads will be properly aligned across scanlines */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLenum format = image->bitmap_bit_order == LSBFirst ?
(!aligned ? GL_BGRA : GL_BGR) :
(!aligned ? GL_RGBA : GL_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, format, GL_UNSIGNED_BYTE, buf);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); /* restore default */
}
XFree(image);
XCloseDisplay(d);
return texture;
}