xserver/test/pyxtest/proto/render.py
Peter Hutterer acbc46e708 pyxtest: add tests for the byteswapping patches
Not a full list since not all can easily be tested but hey, better than
nothing.
See https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2181

Assisted-by: Claude:claude-claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2187>
2026-05-10 23:42:44 +00:00

193 lines
4.8 KiB
Python

# SPDX-License-Identifier: MIT
#
# Render extension protocol request builders
import struct
from dataclasses import dataclass, field
# Render minor opcodes
RenderQueryVersion = 0
RenderQueryPictFormats = 1
RenderCreatePicture = 4
RenderCreateGlyphSet = 17
RenderCompositeGlyphs8 = 23
RenderCompositeGlyphs16 = 24
RenderCompositeGlyphs32 = 25
RenderSetPictureFilter = 30
@dataclass
class QueryVersionRequest:
"""RenderQueryVersion request."""
opcode: int
major: int = 0
minor: int = 11
def to_bytes(self, byte_order: str = "<") -> bytes:
return struct.pack(
f"{byte_order}BBHII",
self.opcode,
RenderQueryVersion,
3,
self.major,
self.minor,
)
@dataclass
class QueryPictFormatsRequest:
"""RenderQueryPictFormats request."""
opcode: int
def to_bytes(self, byte_order: str = "<") -> bytes:
return struct.pack(
f"{byte_order}BBH",
self.opcode,
RenderQueryPictFormats,
1,
)
@dataclass
class CreatePictureRequest:
"""RenderCreatePicture request."""
opcode: int
picture_id: int
drawable: int
format_id: int
value_mask: int = 0
def to_bytes(self, byte_order: str = "<") -> bytes:
return struct.pack(
f"{byte_order}BBHIIII",
self.opcode,
RenderCreatePicture,
5,
self.picture_id,
self.drawable,
self.format_id,
self.value_mask,
)
@dataclass
class CreateGlyphSetRequest:
"""RenderCreateGlyphSet request."""
opcode: int
glyph_set_id: int
format_id: int
def to_bytes(self, byte_order: str = "<") -> bytes:
return struct.pack(
f"{byte_order}BBHII",
self.opcode,
RenderCreateGlyphSet,
3,
self.glyph_set_id,
self.format_id,
)
@dataclass
class _CompositeGlyphsRequestBase:
"""Base class for RenderCompositeGlyphs{8,16,32} requests.
glyph_elts is raw xGlyphElt + glyph ID data.
Subclasses set _minor_opcode for the glyph size (8/16/32 bit IDs).
"""
_minor_opcode: int = field(default=0, init=False, repr=False)
opcode: int = 0
src_picture: int = 0
dst_picture: int = 0
glyph_set: int = 0
mask_format: int = 0
op: int = 3 # PictOpOver
src_x: int = 0
src_y: int = 0
glyph_elts: bytes = b""
def to_bytes(self, byte_order: str = "<") -> bytes:
total = 28 + len(self.glyph_elts)
pad_len = (4 - total % 4) % 4
length = (total + pad_len) // 4
header = struct.pack(
f"{byte_order}BBH BxH IIII hh",
self.opcode,
self._minor_opcode,
length,
self.op,
0, # pad2
self.src_picture,
self.dst_picture,
self.mask_format,
self.glyph_set,
self.src_x,
self.src_y,
)
return header + self.glyph_elts + b"\x00" * pad_len
@dataclass
class CompositeGlyphs8Request(_CompositeGlyphsRequestBase):
"""RenderCompositeGlyphs8 request (minor opcode 23)."""
_minor_opcode: int = field(default=RenderCompositeGlyphs8, init=False, repr=False)
@dataclass
class CompositeGlyphs16Request(_CompositeGlyphsRequestBase):
"""RenderCompositeGlyphs16 request (minor opcode 24)."""
_minor_opcode: int = field(default=RenderCompositeGlyphs16, init=False, repr=False)
@dataclass
class CompositeGlyphs32Request(_CompositeGlyphsRequestBase):
"""RenderCompositeGlyphs32 request (minor opcode 25)."""
_minor_opcode: int = field(default=RenderCompositeGlyphs32, init=False, repr=False)
@dataclass
class SetPictureFilterRequest:
"""RenderSetPictureFilter request.
The filter name is a variable-length string followed by padding,
then xFixed (CARD32) filter parameter values.
"""
opcode: int
picture: int
filter_name: str = "nearest"
params: list[int] | None = None # xFixed values (CARD32)
def to_bytes(self, byte_order: str = "<") -> bytes:
name_bytes = self.filter_name.encode("ascii")
name_len = len(name_bytes)
name_padded = name_bytes + b"\x00" * ((4 - name_len % 4) % 4)
param_data = b""
if self.params:
for p in self.params:
param_data += struct.pack(f"{byte_order}I", p)
total = 12 + len(name_padded) + len(param_data)
pad_len = (4 - total % 4) % 4
length = (total + pad_len) // 4
header = struct.pack(
f"{byte_order}BBH I H xx",
self.opcode,
RenderSetPictureFilter,
length,
self.picture,
name_len,
)
return header + name_padded + param_data + b"\x00" * pad_len