X11::P...MIT_SHM(3pm)
π X11::Protocol::Ext::MIT_SHM β images in SysV style shared memory π
okay bestie, welcome to the manual page for X11::Protocol::Ext::MIT_SHM (perl version 3pm, user contributed, the whole vibe) β¨ this is the part where we make images zoom around through shared memory instead of squeezing them through the I/O pipe like it's 1999. it's giving speed. it's giving efficiency. periodt.
β¨ SYNOPSIS β¨
use X11::Protocol;
my $X = X11::Protocol->new;
$X->init_extension('MIT-SHM')
or print "MIT-SHM extension not available";
use IPC::SysV;
my $shmid = shmget (IPC::SysV::IPC_PRIVATE(),
100000, # bytes
IPC::SysV::IPC_CREAT() | 0666);
my $shmseg = $X->new_rsrc;
$X->MitShmAttach ($shmseg, $shmid, 0);
my ($depth, $visual, $size) = $X->MitShmGetImage
($window, 0,0, 16,16, ~0, 'ZPixmap', $shmseg, 0);
my $image_bytes;
shmread ($shmid, $image_bytes, 0, 16*16*$bpp) || die "$!";
# $image_bytes is the top-left 16x16 pixels of the screen
like, look at that. clean. no notes. π«Ά
πΈ DESCRIPTION πΈ
so the MIT-SHM extension is literally the glow-up that lets a client and a server on the same machine pass image data back and forth through System-V shared memory segments. no network round-trips. just vibes. π₯
the client makes a memory segment with shmget() (peep "shmget" in perlfunc and "SysV IPC" in perlipc if you want the lore), then asks the server to attach to it, and after that it can read or write with equivalents to the core GetImage and PutImage. iconic behavior.
the whole point? avoid yeeting large images through the I/O connection when everything's local. memory is faster, and it can also help you dodge request size limits for very big images. main character energy tbh.
byte order, padding, etc β everything required or generated in images β is specified by the server's $X->{'image_byte_order'}, $X->{'pixmap_formats'}, etc, exactly like the core GetImage() and PutImage(). it's up to the client to adapt to the server's layout, which ngl can be a bit of a chore. π
π§ Shm from Perl π§
a shared memory segment can be created straight from Perl with shmget(), then you read or write its contents with shmread() and shmwrite(). those functions attach and detach it every single time with shmat() and shmdt() system calls. fine for grabbing the whole thing, lowkey slow if you're doing lots of little accesses. π
IPC::SysV (version 2 and up) offers a shmat() to keep the block attached, plus memread() and memwrite() to poke at it (see IPC::SysV). also check out IPC::SharedMem for an object-oriented wrapper around all of this. slay.
also, quick aside: if shmget() isn't available on the system then Perl's shmget() croaks. and it's always possible for it to return undef too, for not enough memory etc. with that, plus not being on the same machine, plus not having identifiable permissions, etc β there's several cases where you'll need a fallback to plain I/O. plan accordingly bestie.
π Shm Permissions π
a SysV shared memory segment has owner/group/other permission bits, kind of like a file. the server will only attach to segments that the requesting client's UID/GID has permission to read or write. no permission, no attach, sorry not sorry.
the server can usually figure out a client's UID/GID on a local connection like a Unix socket (X11::Protocol::Connection::UNIXSocket, and "SO_PEERCRED" in socket(7)), and maybe on a TCP localhost loopback. if it can't? the server treats the client as "other" and will only attach to world-readable (or world read-writable) segments. π
you can make a shm segment world-readable to make sure the server can read it. if the data for a PutImage etc is already from a world-readable file or is just public, then it shouldn't matter much who else reads the segment. just remember to ask for read-only in the MitShmAttach() so the server doesn't want writable too. iykyk.
there's probably no need to risk relaxing permissions for segment writing. chances are that if client UID/GID can't be identified, it's because the connection isn't local and the server is on a different machine β so shared memory can't be used anyway. so like, why bother. π
it's usual for the server to run as root, hence its own permission checks, but it's also possible for the server to be an ordinary user. in that case the shm segments it can access will be limited in the usual way for whatever user it's running as.
π REQUESTS π
these requests are available after an init_extension() per "EXTENSIONS" in X11::Protocol.
my $bool = $X->init_extension('MIT-SHM');
in everything below, $shmid is the shared memory ID (an integer) as obtained from the kernel with shmget(). $shmseg is an XID (allocated as usual by client $X->new_rsrc()) on the server representing the server's attachment to the block. got it? good. π
($server_major, $server_minor, $uid, $gid, $shared_pixmaps, $pixmap_format) = $X->MitShmQueryVersion ()β return information about the MIT-SHM extension. unlike other extensions, there's no client version / server version negotiation here. just facts.
$server_major and $server_minor are the extension version number implemented by the server.
$uid and $gid (integers) are the server's effective user ID and group ID (geteuid() and getegid()). zero means root. π
$shared_pixmaps is non-zero if pixmaps in shared memory are supported (see MitShmCreatePixmap() below). $pixmap_format (an ImageFormat) is XYPixmap or ZPixmap for the layout required in such a pixmap.
$X->MitShmAttach ($shmseg, $shmid, $readonly)β attach the server to a given shared memory segment.$shmsegis a new XID to represent the attached memory.
my $shmseg = $X->new_rsrc;
$X->MitShmAttach ($shmseg, $shmid, 0); # read/write
$shmid is the shared memory ID to attach, as obtained from shmget() (see "shmget" in perlfunc).
$readonly is 1 to have the server attach read-only, or 0 for read-write. read-only suffices for MitShmPutImage(), but read-write is needed for MitShmGetImage() and MitShmCreatePixmap().
$X->MitShmDetach ($shmseg)β detach the server from shared memory$shmseg(an XID) and release that XID.
$X->MitShmDetach ($shmseg);
$X->MitShmPutImage ($drawable, $gc, $depth, $total_width, $total_height, $src_x, $src_y, $src_width, $src_height, $dst_x, $dst_y, $format, $send_event, $shmseg, $offset)β put image data from$shmseg(an XID) to$drawable. the parameters are similar to the corePutImage().
$depth is the depth of the image. for $format Bitmap this must be 1, and the foreground and background colours of $gc are then drawn. for $format XYPixmap and ZPixmap, $depth must be the depth of $drawable.
$total_width,$total_height is the full size of the image in the shared memory. $src_x,$src_y and $src_width,$src_height are the portion of it to draw. $dst_x,$dst_y is where in $drawable to put it.
$format is Bitmap, XYPixmap or ZPixmap (an ImageFormat).
$send_event is 1 to have an MitShmCompletionEvent sent to the client when drawing is finished (see "EVENTS" below), or 0 if that's not wanted.
$offset is a byte offset into the shared memory where the image starts.
($depth, $visual, $size) = $X->MitShmGetImage ($drawable, $x, $y, $width, $height, $planemask, $format, $shmseg, $offset)β copy an image from$drawableto shared memory$shmseg(an XID). the parameters are similar to the coreGetImage().
$x,$y, $width,$height are the part of $drawable to get. $planemask is a bit mask for which bit planes of the pixels are wanted.
$format is XYPixmap or ZPixmap for the layout to be written to the shared memory, and $offset is a byte offset into the memory where the image should start.
the returned $depth (an integer) is the depth of $drawable. $visual (integer ID) is its visual for a window, or None for a pixmap. $size is how many bytes were written.
$shmsegmust be attached read-write in theMitShmAttach()or anAccesserror results. so like, don't skip that step bestie. π
$X->MitShmCreatePixmap ($pixmap, $drawable, $depth, $width, $height, $shmseg, $offset)β create$pixmap(a new XID) as a pixmap with its contents in shared memory$shmseg(an XID). when the client reads or writes that memory, it changes the pixmap contents. the parameters are similar to the coreCreatePixmap().
my $pixmap = $X->new_rsrc;
$X->MitShmCreatePixmap ($pixmap, # new XID
$X->root, # for the screen
$X->root_depth, # depth
10,10, # width,height
$shmseg,
0); # byte offset into shm
the MitShmQueryVersion() request above reports whether shared memory pixmaps are supported, and if so whether they're XYPixmap or ZPixmap layout.
$drawable is used to determine the screen for the new $pixmap. $offset is a byte offset into the shared memory where the pixmap data will begin.
if damage objects from the DAMAGE extension (see X11::Protocol::Ext::DAMAGE) are monitoring a shared $pixmap, then client writes to the shared memory generally don't produce DamageNotify events. the client can use DamageAdd() requests (in Damage version 1.1) to tell the server about changes made, which it will broadcast to interested damage objects. it's probably unusual to have damage objects listening to a shared pixmap though. π
β EVENTS β
MitShmCompletionEvent is sent to the client when requested in an MitShmPutImage(). it says the server has finished reading the memory. bestie said "i'm done reading, you're free." π
the event has the usual fields:
name "MitShmCompletionEvent"
synthetic true if from a SendEvent
code integer opcode
sequence_number integer
and event-specific fields:
drawable XID, target as from request
shmseg XID, source as from request
offset integer, byte offset as from request
major_opcode integer, MIT-SHM extension code
minor_opcode integer, 3 for MitShmPutImage
major_opcode and minor_opcode are the codes of the originating MitShmPutImage(). these fields are similar to the core GraphicsExposure and NoExposure events, but here there's only one request (MitShmPutImage()) which gives a completion event. one request, one event, no drama. π
π¦ ERRORS π¦
error type ShmSeg is a bad $shmseg resource XID in a request.
like, if your $shmseg is giving nothing, this is the error that tells you so. π
π SEE ALSO π
X11::Protocol, "shmget" in perlfunc, "SysV IPC" in perlipc, IPC::SysV, IPC::SharedMem
X11::Protocol::Ext::Damage
/usr/share/doc/x11proto-xext-dev/shm.txt.gz, /usr/share/X11/doc/hardcopy/Xext/mit-shm.PS.gz, ftp://ftp.xfree86.org/pub/mirror/X.Org/pub/R6.6/xc/doc/hardcopy/Xext/mit-shm.PS.gz
π HOME PAGE π
<http://user42.tuxfamily.org/x11-protocol-other/index.html>
okay so that's part 1 bestie β hold on, there's more coming, don't go anywhere π
β¨ LICENSE β¨
ok so legal time bestie, don't scroll π
Copyright 2011 Kevin Ryde β yeah, that's the whole copyright line, we're not being vague about it.
X11-Protocol-Other is free software, fr fr. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation β either version 3, or (at your option) any later version. pick your fighter, both are valid π«Ά
X11-Protocol-Other is distributed in the hope that it will be useful, BUT β and this is the loud part, no cap β it comes with ABSOLUTELY NO WARRANTY, not even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. π like she's out here with zero safety net. See the GNU General Public License for more details if you want the whole saga.
You should have received a copy of the GNU General Public License along with X11-Protocol-Other. If not β and honestly, if you're missing it β see <http://www.gnu.org/licenses/>. that's the link, go get it π
and that's a wrap on the whole page, bestie β¨ this one shipped as part of perl v5.28.1, dated 2019-08-26, living under the name X11::P...MIT_SHM(3pm) in the User Contributed Perl Documentation corner of the world π thanks for reading all the way to the bottom, you're literally the main character π
π¦ where this page comes from
- debian bookworm: libx11-protocol-other-perl 31-1 Β· GPL-3.0-or-later
- debian trixie: libx11-protocol-other-perl 31-1 Β· GPL-3.0-or-later
- ubuntu jammy: libx11-protocol-other-perl 31-1 Β· GPL-3.0-or-later
- ubuntu noble: libx11-protocol-other-perl 31-1 Β· GPL-3.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms