diff --git a/boomer.nimble b/boomer.nimble index 55d080c..8468d22 100644 --- a/boomer.nimble +++ b/boomer.nimble @@ -5,4 +5,4 @@ license = "MIT" srcDir = "src" bin = @["boomer"] -requires "nim >= 0.18.0", "x11 >= 1.1", "opengl >= 1.2.3" +requires "nim >= 0.18.0", "x11 >= 1.1", "opengl >= 1.2.3", "syscall#09c647b0c5798e8d3348f0ed90dbb5704d5e8159" diff --git a/default.nix b/default.nix index 5364bd8..b033d91 100644 --- a/default.nix +++ b/default.nix @@ -10,10 +10,11 @@ in rec { nim_1_0 xorg.libX11 xorg.libXrandr + xorg.libXext libGL libGLU freeglut ]; - LD_LIBRARY_PATH="/run/opengl-driver/lib;${xorg.libX11}/lib/;${libGL}/lib/;${libGLU}/lib;${freeglut}/lib;${xorg.libXrandr}/lib"; + LD_LIBRARY_PATH="/run/opengl-driver/lib;${xorg.libX11}/lib/;${libGL}/lib/;${libGLU}/lib;${freeglut}/lib;${xorg.libXrandr}/lib;${xorg.libXext}/lib"; }; } diff --git a/src/boomer.nim b/src/boomer.nim index e75bca5..de1a73c 100644 --- a/src/boomer.nim +++ b/src/boomer.nim @@ -4,13 +4,19 @@ import navigation import image import config -import x11/xlib, x11/x, x11/xutil, x11/keysym, x11/xrandr +import x11/xlib, x11/x, x11/xutil, x11/keysym, x11/xrandr, x11/xshm import opengl, opengl/glx import math import la +import syscall type Shader = tuple[path, content: string] +const + IPC_PRIVATE = 0 + IPC_CREAT = 512 + IPC_RMID = 0 + proc readShader(file: string): Shader = when nimvm: result.path = file @@ -146,9 +152,6 @@ proc main() = let rate = XRRConfigCurrentRate(screenConfig) echo "Screen rate: ", rate - var screenshot = takeScreenshot(display, root) - assert screenshot.bits_per_pixel == 32 - let screen = XDefaultScreen(display) var glxMajor, glxMinor: int @@ -170,6 +173,7 @@ proc main() = if vi == nil: quit "No appropriate visual found" + echo "Visual ", vi.visualid, " selected" var swa: TXSetWindowAttributes swa.colormap = XCreateColormap(display, root, @@ -177,9 +181,36 @@ proc main() = swa.event_mask = ButtonPressMask or ButtonReleaseMask or KeyPressMask or PointerMotionMask or ExposureMask or ClientMessage + var attributes: TXWindowAttributes + discard XGetWindowAttributes( + display, + DefaultRootWindow(display), + addr attributes) + + var shminfo: TXShmSegmentInfo + var screenshot = XShmCreateImage( + display, vi.visual, 24.cuint, ZPixmap, nil, + addr shminfo, + attributes.width.cuint, + attributes.height.cuint) + + shminfo.shmid = syscall(SHMGET, + IPC_PRIVATE, + screenshot.bytes_per_line * screenshot.height, + 1023).cint + shminfo.shmaddr = cast[cstring](syscall(SHMAT, shminfo.shmid, 0, 0)) + screenshot.data = shminfo.shmaddr + shminfo.readOnly = 0 + + let err = XShmAttach(display, addr shminfo) + echo "Status of XShmAttach call = ", err + discard XSync(display, 0) + + discard XShmGetImage(display, DefaultRootWindow(display), screenshot, 0.cint, 0.cint, AllPlanes); + var win = XCreateWindow( display, root, - 0, 0, screenshot.width.cuint, screenshot.height.cuint, 0, + 0, 0, attributes.width.cuint, attributes.height.cuint, 0, vi.depth, InputOutput, vi.visual, CWColormap or CWEventMask, addr swa) @@ -389,6 +420,18 @@ proc main() = glXSwapBuffers(display, win) glFinish() + discard XShmGetImage(display, DefaultRootWindow(display), screenshot, 0.cint, 0.cint, AllPlanes); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGB.GLint, + screenshot.width, + screenshot.height, + 0, + # TODO(#13): the texture format is hardcoded + GL_BGRA, + GL_UNSIGNED_BYTE, + screenshot.data) + when defined(live): screenshot = XGetSubImage(display, root, 0, 0, diff --git a/src/shmack.nim b/src/shmack.nim new file mode 100644 index 0000000..194be5e --- /dev/null +++ b/src/shmack.nim @@ -0,0 +1,67 @@ +import x11/xlib # of course +import x11/xutil +import x11/xshm +import x11/x + +import syscall +import image + +const + IPC_PRIVATE = 0 + IPC_CREAT = 512 + IPC_RMID = 0 + +block: + let display = XOpenDisplay(nil) + defer: + discard display.XCloseDisplay + + var major, minor: cint + var pixmaps: TBool + discard XShmQueryVersion(display, addr major, addr minor, addr pixmaps) + echo "SHM Version ", major, ".", minor, ", Pixmaps supported: ", pixmaps + + var vinfo: TXVisualInfo + discard XMatchVisualInfo( + display, + XDefaultScreen(display), + 24, + TrueColor, + addr vinfo) + + var attributes: TXWindowAttributes + discard XGetWindowAttributes( + display, + DefaultRootWindow(display), + addr attributes) + + var shminfo: TXShmSegmentInfo + var image = XShmCreateImage( + display, vinfo.visual, 24.cuint, ZPixmap, nil, + addr shminfo, + attributes.width.cuint, + attributes.height.cuint) + + shminfo.shmid = syscall(SHMGET, + IPC_PRIVATE, + image.bytes_per_line * image.height, + 1023).cint + echo "shminfo.shmid = ", shminfo.shmid + + shminfo.shmaddr = cast[cstring](syscall(SHMAT, shminfo.shmid, 0, 0)) + image.data = shminfo.shmaddr + shminfo.readOnly = 0 + + let err = XShmAttach(display, addr shminfo) + echo "Status of XShmAttach call = ", err + discard XSync(display, 0) + + discard XShmGetImage(display, DefaultRootWindow(display), image, 0.cint, 0.cint, AllPlanes); + discard XSync(display, 0); + + image.saveToPPM("nim-shmack.ppm") + + discard XShmDetach(display, addr shminfo) + discard XDestroyImage(image) + discard syscall(SHMDT, shminfo.shmaddr) + discard syscall(SHMCTL, shminfo.shmid, IPC_RMID, 0)