refactored X11 code in 'render.c' and 'xwin.c'
This commit is contained in:
2
Makefile
2
Makefile
@@ -43,7 +43,7 @@ ifeq ($(INSTALL),osx)
|
|||||||
SHADER_DIR = Library/glava
|
SHADER_DIR = Library/glava
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDFLAGS = $(ASAN) -lpulse -lpulse-simple -pthread -lglfw -ldl -lm -lX11 -lXext
|
LDFLAGS = $(ASAN) -lpulse -lpulse-simple -pthread -lglfw -ldl -lm -lX11 -lXext -lXcomposite
|
||||||
|
|
||||||
PYTHON = python
|
PYTHON = python
|
||||||
|
|
||||||
|
|||||||
2
glava.c
2
glava.c
@@ -274,7 +274,7 @@ int main(int argc, char** argv) {
|
|||||||
pthread_mutex_unlock(&audio.mutex);
|
pthread_mutex_unlock(&audio.mutex);
|
||||||
|
|
||||||
/* Only render if needed (ie. stop rendering when fullscreen windows are focused) */
|
/* Only render if needed (ie. stop rendering when fullscreen windows are focused) */
|
||||||
if (xwin_should_render()) {
|
if (xwin_should_render(r)) {
|
||||||
rd_update(r, lb, rb, r->bufsize_request, modified);
|
rd_update(r, lb, rb, r->bufsize_request, modified);
|
||||||
} else {
|
} else {
|
||||||
/* Sleep for 50ms and then attempt to render again */
|
/* Sleep for 50ms and then attempt to render again */
|
||||||
|
|||||||
21
render.c
21
render.c
@@ -16,6 +16,18 @@
|
|||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
|
|
||||||
|
/* Hack to make GLFW 3.1 headers work with GLava. We don't use the context APIs from GLFW, but
|
||||||
|
the old headers require one of them to be selected for exposure in glfw3native.h. */
|
||||||
|
#if GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR <= 1
|
||||||
|
#define GLFW_EXPOSE_NATIVE_GLX
|
||||||
|
#endif
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
|
||||||
/* Fixes for old GLFW versions */
|
/* Fixes for old GLFW versions */
|
||||||
#ifndef GLFW_TRUE
|
#ifndef GLFW_TRUE
|
||||||
#define GLFW_TRUE GL_TRUE
|
#define GLFW_TRUE GL_TRUE
|
||||||
@@ -98,6 +110,7 @@ struct overlay_data {
|
|||||||
struct gl_data {
|
struct gl_data {
|
||||||
struct gl_sfbo* stages;
|
struct gl_sfbo* stages;
|
||||||
struct overlay_data overlay;
|
struct overlay_data overlay;
|
||||||
|
Display* display;
|
||||||
GLuint audio_tex_r, audio_tex_l, bg_tex, sm_prog;
|
GLuint audio_tex_r, audio_tex_l, bg_tex, sm_prog;
|
||||||
size_t stages_sz, bufscale, avg_frames;
|
size_t stages_sz, bufscale, avg_frames;
|
||||||
GLFWwindow* w;
|
GLFWwindow* w;
|
||||||
@@ -117,6 +130,8 @@ struct gl_data {
|
|||||||
int geometry[4];
|
int geometry[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* load shader file */
|
/* load shader file */
|
||||||
static GLuint shaderload(const char* rpath,
|
static GLuint shaderload(const char* rpath,
|
||||||
GLenum type,
|
GLenum type,
|
||||||
@@ -732,6 +747,8 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
|
|||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
|
gl->display = glfwGetX11Display();
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);
|
glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);
|
||||||
@@ -1576,6 +1593,10 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* rd_get_impl_window(struct renderer* r) { return r->gl->w; }
|
void* rd_get_impl_window(struct renderer* r) { return r->gl->w; }
|
||||||
|
Display* rd_get_x11_display(struct renderer* r) { return r->gl->display; }
|
||||||
|
Window rd_get_x11_window(struct renderer* r) { return glfwGetX11Window(r->gl->w); }
|
||||||
|
void rd_get_fbsize(struct renderer* r, int* w, int* h) { glfwGetFramebufferSize(r->gl->w, w, h); }
|
||||||
|
void rd_get_wpos(struct renderer* r, int* x, int* y) { glfwGetWindowPos(r->gl->w, x, y); }
|
||||||
|
|
||||||
void rd_destroy(struct renderer* r) {
|
void rd_destroy(struct renderer* r) {
|
||||||
/* TODO: delete everything else, not really needed though (as the application exits after here) */
|
/* TODO: delete everything else, not really needed though (as the application exits after here) */
|
||||||
|
|||||||
16
render.h
16
render.h
@@ -8,8 +8,16 @@ typedef struct renderer {
|
|||||||
struct gl_data* gl;
|
struct gl_data* gl;
|
||||||
} renderer;
|
} renderer;
|
||||||
|
|
||||||
struct renderer* rd_new(const char** paths, const char* entry, const char* force_mod);
|
struct renderer* rd_new (const char** paths, const char* entry,
|
||||||
void rd_update(struct renderer*, float* lb, float* rb, size_t bsz, bool modified);
|
const char* force_mod);
|
||||||
void rd_destroy(struct renderer*);
|
void rd_update (struct renderer*, float* lb, float* rb,
|
||||||
void rd_time(struct renderer*);
|
size_t bsz, bool modified);
|
||||||
|
void rd_destroy (struct renderer*);
|
||||||
|
void rd_time (struct renderer*);
|
||||||
void* rd_get_impl_window(struct renderer*);
|
void* rd_get_impl_window(struct renderer*);
|
||||||
|
void rd_get_fbsize (struct renderer*, int* w, int* h);
|
||||||
|
void rd_get_wpos (struct renderer*, int* x, int* y);
|
||||||
|
#ifdef GLAVA_RDX11
|
||||||
|
Display* rd_get_x11_display(struct renderer*);
|
||||||
|
Window rd_get_x11_window (struct renderer*);
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
/* GLFW window hints */
|
/* GLFW window hints */
|
||||||
#request setfloating false
|
#request setfloating false
|
||||||
#request setdecorated false
|
#request setdecorated true
|
||||||
#request setfocused false
|
#request setfocused false
|
||||||
#request setmaximized false
|
#request setmaximized false
|
||||||
|
|
||||||
|
|||||||
228
xwin.c
228
xwin.c
@@ -12,30 +12,21 @@
|
|||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/extensions/Xcomposite.h>
|
||||||
#include <X11/extensions/XShm.h>
|
#include <X11/extensions/XShm.h>
|
||||||
|
|
||||||
#define GLFW_EXPOSE_NATIVE_X11
|
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
/* Hack to make GLFW 3.1 headers work with GLava. We don't use the context APIs from GLFW, but
|
|
||||||
the old headers require one of them to be selected for exposure in glfw3native.h. */
|
|
||||||
#if GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR <= 1
|
|
||||||
#define GLFW_EXPOSE_NATIVE_GLX
|
|
||||||
#endif
|
|
||||||
#include <GLFW/glfw3native.h>
|
|
||||||
|
|
||||||
|
#define GLAVA_RDX11
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "xwin.h"
|
|
||||||
|
|
||||||
|
static Window find_desktop(struct renderer* r) {
|
||||||
static Window find_desktop(void) {
|
|
||||||
static Window desktop;
|
static Window desktop;
|
||||||
static bool searched = false;
|
static bool searched = false;
|
||||||
if (!searched) {
|
if (!searched) {
|
||||||
Display* d = glfwGetX11Display();
|
Display* d = rd_get_x11_display(r);
|
||||||
desktop = DefaultRootWindow(d);
|
desktop = DefaultRootWindow(d);
|
||||||
Window _ignored, * children;
|
Window _ignored, * children;
|
||||||
unsigned int nret;
|
unsigned int nret;
|
||||||
@@ -47,7 +38,8 @@ static Window find_desktop(void) {
|
|||||||
if (name) {
|
if (name) {
|
||||||
/* Mutter-based window managers */
|
/* Mutter-based window managers */
|
||||||
if (!strcmp(name, "mutter guard window")) {
|
if (!strcmp(name, "mutter guard window")) {
|
||||||
desktop = children[t];
|
printf("Using mutter guard window instead of root window\n");
|
||||||
|
// desktop = children[t];
|
||||||
t = nret; /* break after */
|
t = nret; /* break after */
|
||||||
}
|
}
|
||||||
XFree(name);
|
XFree(name);
|
||||||
@@ -60,9 +52,9 @@ static Window find_desktop(void) {
|
|||||||
return desktop;
|
return desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xwin_should_render(void) {
|
bool xwin_should_render(struct renderer* rd) {
|
||||||
bool ret = true, should_close = false;
|
bool ret = true, should_close = false;
|
||||||
Display* d = glfwGetX11Display();
|
Display* d = rd_get_x11_display(rd);
|
||||||
if (!d) {
|
if (!d) {
|
||||||
d = XOpenDisplay(0);
|
d = XOpenDisplay(0);
|
||||||
should_close = true;
|
should_close = true;
|
||||||
@@ -107,8 +99,8 @@ bool xwin_should_render(void) {
|
|||||||
/* Set window types defined by the EWMH standard, possible values:
|
/* Set window types defined by the EWMH standard, possible values:
|
||||||
-> "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal" */
|
-> "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal" */
|
||||||
static void xwin_changeatom(struct renderer* rd, const char* type, const char* atom, const char* fmt, int mode) {
|
static void xwin_changeatom(struct renderer* rd, const char* type, const char* atom, const char* fmt, int mode) {
|
||||||
Window w = glfwGetX11Window((GLFWwindow*) rd_get_impl_window(rd));
|
Window w = rd_get_x11_window(rd);
|
||||||
Display* d = glfwGetX11Display();
|
Display* d = rd_get_x11_display(rd);
|
||||||
Atom wtype = XInternAtom(d, atom, false);
|
Atom wtype = XInternAtom(d, atom, false);
|
||||||
size_t len = strlen(type), t;
|
size_t len = strlen(type), t;
|
||||||
char formatted[len + 1];
|
char formatted[len + 1];
|
||||||
@@ -133,8 +125,8 @@ void xwin_addstate(struct renderer* rd, const char* state) {
|
|||||||
xwin_changeatom(rd, state, "_NET_WM_STATE", "_NET_WM_STATE_%s", PropModeAppend);
|
xwin_changeatom(rd, state, "_NET_WM_STATE", "_NET_WM_STATE_%s", PropModeAppend);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Pixmap get_pixmap(Display* d, Window w) {
|
static Drawable get_drawable(Display* d, Window w) {
|
||||||
Pixmap p;
|
Drawable p;
|
||||||
Atom act_type;
|
Atom act_type;
|
||||||
int act_format;
|
int act_format;
|
||||||
unsigned long nitems, bytes_after;
|
unsigned long nitems, bytes_after;
|
||||||
@@ -142,14 +134,14 @@ static Pixmap get_pixmap(Display* d, Window w) {
|
|||||||
Atom id;
|
Atom id;
|
||||||
|
|
||||||
id = XInternAtom(d, "_XROOTPMAP_ID", False);
|
id = XInternAtom(d, "_XROOTPMAP_ID", False);
|
||||||
|
|
||||||
if (XGetWindowProperty(d, w, id, 0, 1, False, XA_PIXMAP,
|
if (XGetWindowProperty(d, w, id, 0, 1, False, XA_PIXMAP,
|
||||||
&act_type, &act_format, &nitems, &bytes_after,
|
&act_type, &act_format, &nitems, &bytes_after,
|
||||||
&data) == Success) {
|
&data) == Success && data) {
|
||||||
if (data) {
|
p = *((Pixmap *) data);
|
||||||
p = *((Pixmap *) data);
|
XFree(data);
|
||||||
XFree(data);
|
} else {
|
||||||
}
|
p = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
@@ -163,113 +155,123 @@ unsigned int xwin_copyglbg(struct renderer* rd, unsigned int tex) {
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
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_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
GLFWwindow* gwin = (GLFWwindow*) rd_get_impl_window(rd);
|
bool use_shm = true;
|
||||||
|
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
glfwGetFramebufferSize(gwin, &w, &h);
|
rd_get_fbsize(rd, &w, &h);
|
||||||
glfwGetWindowPos(gwin, &x, &y);
|
rd_get_wpos(rd, &x, &y);
|
||||||
XColor c;
|
XColor c;
|
||||||
Display* d = glfwGetX11Display();
|
Display* d = rd_get_x11_display(rd);
|
||||||
Pixmap p = get_pixmap(d, find_desktop());
|
Drawable src = get_drawable(d, find_desktop(rd));
|
||||||
|
|
||||||
/* Obtain section of root pixmap using XShm */
|
/* Obtain section of root pixmap */
|
||||||
|
|
||||||
XShmSegmentInfo shminfo;
|
XShmSegmentInfo shminfo;
|
||||||
Visual* visual = DefaultVisual(d, DefaultScreen(d));
|
Visual* visual = DefaultVisual(d, DefaultScreen(d));
|
||||||
XVisualInfo match = { .visualid = XVisualIDFromVisual(visual) };
|
XVisualInfo match = { .visualid = XVisualIDFromVisual(visual) };
|
||||||
int nret;
|
int nret;
|
||||||
XVisualInfo* info = XGetVisualInfo(d, VisualIDMask, &match, &nret);
|
XVisualInfo* info = XGetVisualInfo(d, VisualIDMask, &match, &nret);
|
||||||
XImage* image = XShmCreateImage(d, visual, info->depth, ZPixmap, NULL,
|
XImage* image;
|
||||||
&shminfo, (unsigned int) w, (unsigned int) h);
|
if (use_shm) {
|
||||||
if ((shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
|
image = XShmCreateImage(d, visual, info->depth, ZPixmap, NULL,
|
||||||
IPC_CREAT | 0777)) == -1) {
|
&shminfo, (unsigned int) w, (unsigned int) h);
|
||||||
fprintf(stderr, "shmget() failed: %s\n", strerror(errno));
|
if ((shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height,
|
||||||
exit(EXIT_FAILURE);
|
IPC_CREAT | 0777)) == -1) {
|
||||||
|
fprintf(stderr, "shmget() failed: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
|
||||||
|
shminfo.readOnly = false;
|
||||||
|
XShmAttach(d, &shminfo);
|
||||||
|
XShmGetImage(d, src, image, x, y, AllPlanes);
|
||||||
|
} else {
|
||||||
|
image = XGetImage(d, src, x, y, (unsigned int) w, (unsigned int) h,
|
||||||
|
ZPixmap, AllPlanes);
|
||||||
}
|
}
|
||||||
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\
|
/* Try to convert pixel bit depth to OpenGL storage format. The following formats\
|
||||||
will need intermediate conversion before OpenGL can accept the data:
|
will need intermediate conversion before OpenGL can accept the data:
|
||||||
|
|
||||||
- 8-bit pixel formats (retro displays, low-bandwidth virtual displays)
|
- 8-bit pixel formats (retro displays, low-bandwidth virtual displays)
|
||||||
- 36-bit pixel formats (rare deep color displays) */
|
- 36-bit pixel formats (rare deep color displays) */
|
||||||
|
|
||||||
bool invalid = false, aligned = false;
|
if (image) {
|
||||||
GLenum type;
|
bool invalid = false, aligned = false;
|
||||||
switch (image->bits_per_pixel) {
|
GLenum type;
|
||||||
case 16:
|
switch (image->bits_per_pixel) {
|
||||||
switch (image->depth) {
|
case 16:
|
||||||
case 12: type = GL_UNSIGNED_SHORT_4_4_4_4; break; /* 12-bit (rare) */
|
switch (image->depth) {
|
||||||
case 15: type = GL_UNSIGNED_SHORT_5_5_5_1; break; /* 15-bit, hi-color */
|
case 12: type = GL_UNSIGNED_SHORT_4_4_4_4; break; /* 12-bit (rare) */
|
||||||
case 16: /* 16-bit, hi-color */
|
case 15: type = GL_UNSIGNED_SHORT_5_5_5_1; break; /* 15-bit, hi-color */
|
||||||
type = GL_UNSIGNED_SHORT_5_6_5;
|
case 16: /* 16-bit, hi-color */
|
||||||
aligned = true;
|
type = GL_UNSIGNED_SHORT_5_6_5;
|
||||||
break;
|
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;
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
uint8_t* buf;
|
||||||
free(buf);
|
if (invalid) {
|
||||||
} else {
|
abort();
|
||||||
/* Use image data directly. The alpha value is garbage/unassigned data, but
|
/* Manual reformat (slow) */
|
||||||
we need to read it because X11 keeps pixel data aligned */
|
buf = malloc(4 * w * h);
|
||||||
buf = (uint8_t*) image->data;
|
int xi, yi;
|
||||||
/* Data could be 2, 4, or 8 byte aligned, the RGBA format and type (depth)
|
Colormap map = DefaultColormap(d, DefaultScreen(d));
|
||||||
already ensures reads will be properly aligned across scanlines */
|
for (yi = 0; yi < h; ++yi) {
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
for (xi = 0; xi < w; ++xi) {
|
||||||
GLenum format = image->bitmap_bit_order == LSBFirst ?
|
c.pixel = XGetPixel(image, xi, yi);
|
||||||
(!aligned ? GL_BGRA : GL_BGR) :
|
XQueryColor(d, map, &c);
|
||||||
(!aligned ? GL_RGBA : GL_RGB);
|
size_t base = (xi + (yi * w)) * 4;
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, format, type, buf);
|
buf[base + 0] = c.red / 256;
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); /* restore default */
|
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 = (uint8_t*) 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, type, buf);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); /* restore default */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (use_shm) {
|
||||||
|
XShmDetach(d, &shminfo);
|
||||||
|
shmdt(shminfo.shmaddr);
|
||||||
|
shmctl(shminfo.shmid, IPC_RMID, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
XShmDetach(d, &shminfo);
|
if (image) XDestroyImage(image);
|
||||||
shmdt(shminfo.shmaddr);
|
|
||||||
shmctl(shminfo.shmid, IPC_RMID, NULL);
|
|
||||||
|
|
||||||
XDestroyImage(image);
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|||||||
2
xwin.h
2
xwin.h
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
bool xwin_should_render(void);
|
bool xwin_should_render(struct renderer* rd);
|
||||||
void xwin_settype(struct renderer* rd, const char* type);
|
void xwin_settype(struct renderer* rd, const char* type);
|
||||||
void xwin_addstate(struct renderer* rd, const char* state);
|
void xwin_addstate(struct renderer* rd, const char* state);
|
||||||
unsigned int xwin_copyglbg(struct renderer* rd, unsigned int texture);
|
unsigned int xwin_copyglbg(struct renderer* rd, unsigned int texture);
|
||||||
|
|||||||
Reference in New Issue
Block a user