From c21d77726985379ae71b346cc51b6ea01c4136d6 Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 8 Dec 2025 15:38:49 -0500 Subject: [PATCH] screenshot: flip bits for RGB888 --- core/internal/colorpicker/picker.go | 15 ++++++++++++++- core/internal/colorpicker/shm.go | 15 +++++++++++++++ core/internal/colorpicker/state.go | 14 ++++++++++++++ core/internal/wayland/shm/buffer.go | 22 ++++++++++++++-------- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/core/internal/colorpicker/picker.go b/core/internal/colorpicker/picker.go index f9309371..bd5dff17 100644 --- a/core/internal/colorpicker/picker.go +++ b/core/internal/colorpicker/picker.go @@ -30,6 +30,7 @@ type Output struct { height int32 scale int32 fractionalScale float64 + transform int32 } type LayerSurface struct { @@ -276,6 +277,7 @@ func (p *Picker) setupOutputHandlers(name uint32, output *client.Output) { if o, ok := p.outputs[name]; ok { o.x = e.X o.y = e.Y + o.transform = int32(e.Transform) } p.outputsMu.Unlock() }) @@ -485,8 +487,19 @@ func (p *Picker) captureForSurface(ls *LayerSurface) { frame.SetReadyHandler(func(e wlr_screencopy.ZwlrScreencopyFrameV1ReadyEvent) { ls.state.OnScreencopyReady() - logicalW, _ := ls.state.LogicalSize() screenBuf := ls.state.ScreenBuffer() + if screenBuf != nil && ls.output.transform != TransformNormal { + invTransform := InverseTransform(ls.output.transform) + transformed, err := screenBuf.ApplyTransform(invTransform) + if err != nil { + log.Error("apply transform failed", "err", err) + } else if transformed != screenBuf { + ls.state.ReplaceScreenBuffer(transformed) + } + } + + logicalW, _ := ls.state.LogicalSize() + screenBuf = ls.state.ScreenBuffer() if logicalW > 0 && screenBuf != nil { ls.output.fractionalScale = float64(screenBuf.Width) / float64(logicalW) } diff --git a/core/internal/colorpicker/shm.go b/core/internal/colorpicker/shm.go index 939dd520..6ee9dc03 100644 --- a/core/internal/colorpicker/shm.go +++ b/core/internal/colorpicker/shm.go @@ -4,10 +4,25 @@ import "github.com/AvengeMedia/DankMaterialShell/core/internal/wayland/shm" type ShmBuffer = shm.Buffer +const ( + TransformNormal = shm.TransformNormal + Transform90 = shm.Transform90 + Transform180 = shm.Transform180 + Transform270 = shm.Transform270 + TransformFlipped = shm.TransformFlipped + TransformFlipped90 = shm.TransformFlipped90 + TransformFlipped180 = shm.TransformFlipped180 + TransformFlipped270 = shm.TransformFlipped270 +) + func CreateShmBuffer(width, height, stride int) (*ShmBuffer, error) { return shm.CreateBuffer(width, height, stride) } +func InverseTransform(transform int32) int32 { + return shm.InverseTransform(transform) +} + func GetPixelColor(buf *ShmBuffer, x, y int) Color { return GetPixelColorWithFormat(buf, x, y, FormatARGB8888) } diff --git a/core/internal/colorpicker/state.go b/core/internal/colorpicker/state.go index 9041fbf8..d9278a3f 100644 --- a/core/internal/colorpicker/state.go +++ b/core/internal/colorpicker/state.go @@ -115,6 +115,20 @@ func (s *SurfaceState) ScreenFormat() PixelFormat { return s.screenFormat } +func (s *SurfaceState) ReplaceScreenBuffer(newBuf *ShmBuffer) { + s.mu.Lock() + defer s.mu.Unlock() + + if s.screenBuf != nil { + s.screenBuf.Close() + } + s.screenBuf = newBuf + s.screenFormat = newBuf.Format + + s.recomputeScale() + s.ensureRenderBuffers() +} + func (s *SurfaceState) OnScreencopyFlags(flags uint32) { s.mu.Lock() s.yInverted = (flags & 1) != 0 diff --git a/core/internal/wayland/shm/buffer.go b/core/internal/wayland/shm/buffer.go index 64e61b29..9cfee205 100644 --- a/core/internal/wayland/shm/buffer.go +++ b/core/internal/wayland/shm/buffer.go @@ -109,7 +109,11 @@ func (b *Buffer) ConvertTo32Bit(srcFormat PixelFormat) (*Buffer, PixelFormat, er srcData := b.data dstData := dst.data - isRGB := srcFormat == FormatRGB888 + + // DRM format names are counterintuitive on little-endian: + // RGB888 memory layout: B, G, R (name is logical order, not memory) + // BGR888 memory layout: R, G, B + isBGRMemory := srcFormat == FormatRGB888 for y := 0; y < b.Height; y++ { srcRow := y * b.Stride @@ -117,14 +121,16 @@ func (b *Buffer) ConvertTo32Bit(srcFormat PixelFormat) (*Buffer, PixelFormat, er for x := 0; x < b.Width; x++ { si := srcRow + x*3 di := dstRow + x*4 - if isRGB { - dstData[di+0] = srcData[si+2] // B - dstData[di+1] = srcData[si+1] // G - dstData[di+2] = srcData[si+0] // R + if isBGRMemory { + // RGB888: src memory is B,G,R -> dst XRGB8888 memory B,G,R,X + dstData[di+0] = srcData[si+0] + dstData[di+1] = srcData[si+1] + dstData[di+2] = srcData[si+2] } else { - dstData[di+0] = srcData[si+0] // B - dstData[di+1] = srcData[si+1] // G - dstData[di+2] = srcData[si+2] // R + // BGR888: src memory is R,G,B -> dst XRGB8888 memory B,G,R,X + dstData[di+0] = srcData[si+2] + dstData[di+1] = srcData[si+1] + dstData[di+2] = srcData[si+0] } dstData[di+3] = 0xFF }