Implement ShmGetImage
Also SHM extension is now only compiled if the system has shmat and shmdt
This commit is contained in:
parent
188f9182ea
commit
632787b142
|
|
@ -2780,63 +2780,36 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||
dprintln(" planeMask: {}", request.planeMask);
|
||||
|
||||
auto& object = *g_objects[request.drawable];
|
||||
auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object);
|
||||
auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object);
|
||||
|
||||
uint8_t bpp = 0;
|
||||
for (const auto& format : g_formats)
|
||||
if (format.depth == out_depth)
|
||||
bpp = format.bitsPerPixel;
|
||||
ASSERT(bpp && 32 % bpp == 0);
|
||||
const auto dwords = image_dwords(request.width, request.height, in_depth);
|
||||
|
||||
ASSERT(request.x >= 0 && request.y >= 0);
|
||||
ASSERT(request.x + request.width <= out_w);
|
||||
ASSERT(request.y + request.height <= out_h);
|
||||
|
||||
const CARD32 length = (request.width * bpp + 31) / 32 * request.height;
|
||||
xGetImageReply reply {
|
||||
.type = X_Reply,
|
||||
.depth = out_depth,
|
||||
.depth = in_depth,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = length,
|
||||
.length = dwords,
|
||||
.visual = g_visual.visualID,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
if (request.format != ZPixmap)
|
||||
dwarnln("GetImage with format {}", request.format);
|
||||
const auto old_size = client_info.output_buffer.size();
|
||||
TRY(client_info.output_buffer.resize(old_size + dwords * 4));
|
||||
|
||||
if (bpp == 32)
|
||||
{
|
||||
for (int32_t y = 0; y < request.height; y++)
|
||||
{
|
||||
const size_t index = (request.y + y) * out_w + request.x;
|
||||
const auto slice = out_data.slice(index * 4, request.width * 4);
|
||||
TRY(encode(client_info.output_buffer, slice));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BAN::Vector<uint32_t> scanline;
|
||||
TRY(scanline.resize((request.width * bpp + 31) / 32));
|
||||
auto* out_data = client_info.output_buffer.data() + old_size;
|
||||
|
||||
for (int32_t y = 0; y < request.height; y++)
|
||||
{
|
||||
for (auto& dword : scanline)
|
||||
dword = 0;
|
||||
|
||||
const auto row_off = (request.y + y) * out_w;
|
||||
for (int32_t x = 0; x < request.width; x++)
|
||||
{
|
||||
const auto bit_offset = x * bpp;
|
||||
const auto dword = bit_offset / 32;
|
||||
const auto shift = bit_offset % 32;
|
||||
const auto mask = (1u << bpp) - 1;
|
||||
scanline[dword] |= (out_data[row_off + (request.x + x)] & mask) << shift;
|
||||
}
|
||||
|
||||
TRY(encode(client_info.output_buffer, scanline));
|
||||
}
|
||||
}
|
||||
get_image({
|
||||
.out_data = out_data,
|
||||
.in_data = in_data.data(),
|
||||
.in_x = request.x,
|
||||
.in_y = request.y,
|
||||
.in_w = in_w,
|
||||
.in_h = in_h,
|
||||
.w = request.width,
|
||||
.h = request.height,
|
||||
.depth = in_depth,
|
||||
.format = request.format,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,18 @@ set(SOURCES
|
|||
Extensions.cpp
|
||||
ExtBigReg.cpp
|
||||
ExtRANDR.cpp
|
||||
ExtSHM.cpp
|
||||
Image.cpp
|
||||
Keymap.cpp
|
||||
)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
|
||||
check_symbol_exists(shmat "sys/shm.h" HAVE_SHMAT)
|
||||
check_symbol_exists(shmdt "sys/shm.h" HAVE_SHMDT)
|
||||
if(HAVE_SHMAT AND HAVE_SHMDT)
|
||||
set(SOURCES ${SOURCES} ExtSHM.cpp)
|
||||
endif()
|
||||
|
||||
add_executable(xbanan ${SOURCES})
|
||||
banan_link_library(xbanan ban)
|
||||
banan_link_library(xbanan libgui)
|
||||
|
|
|
|||
|
|
@ -258,6 +258,53 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||
|
||||
break;
|
||||
}
|
||||
case X_ShmGetImage:
|
||||
{
|
||||
auto request = decode<xShmGetImageReq>(packet).value();
|
||||
|
||||
dprintln("ShmGetImage");
|
||||
dprintln(" drawable: {}", request.drawable);
|
||||
dprintln(" x: {}", request.x);
|
||||
dprintln(" y: {}", request.y);
|
||||
dprintln(" wigth: {}", request.width);
|
||||
dprintln(" height: {}", request.height);
|
||||
dprintln(" planeMask: {}", request.planeMask);
|
||||
dprintln(" format: {}", request.format);
|
||||
dprintln(" shmseg: {}", request.shmseg);
|
||||
dprintln(" offset: {}", request.offset);
|
||||
|
||||
auto& shm_segment = s_shm_segments[request.shmseg];
|
||||
|
||||
auto& object = TRY_REF(get_drawable(request.drawable));
|
||||
auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object);
|
||||
|
||||
const auto dwords = image_dwords(request.width, request.height, in_depth);
|
||||
|
||||
get_image({
|
||||
.out_data = (uint8_t*)shm_segment.addr + request.offset,
|
||||
.in_data = in_data.data(),
|
||||
.in_x = request.x,
|
||||
.in_y = request.y,
|
||||
.in_w = in_w,
|
||||
.in_h = in_h,
|
||||
.w = request.width,
|
||||
.h = request.height,
|
||||
.depth = in_depth,
|
||||
.format = request.format,
|
||||
});
|
||||
|
||||
xShmGetImageReply reply {
|
||||
.type = X_Reply,
|
||||
.depth = in_depth,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.visual = g_visual.visualID,
|
||||
.size = dwords * 4,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dwarnln("unsupported shm minor opcode {}", packet[1]);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@
|
|||
|
||||
#include <X11/X.h>
|
||||
|
||||
uint32_t image_dwords(uint32_t width, uint32_t height, uint8_t depth)
|
||||
{
|
||||
uint8_t bpp = 0;
|
||||
for (const auto& format : g_formats)
|
||||
if (format.depth == depth)
|
||||
bpp = format.bitsPerPixel;
|
||||
ASSERT(bpp && 32 % bpp == 0);
|
||||
return (width * bpp + 31) / 32 * height;
|
||||
}
|
||||
|
||||
void put_image(const PutImageInfo& info)
|
||||
{
|
||||
uint8_t in_bpp = 0;
|
||||
|
|
@ -20,11 +30,7 @@ void put_image(const PutImageInfo& info)
|
|||
auto* out_data_u32 = static_cast<uint32_t*>(info.out_data);
|
||||
const auto* in_data_u32 = static_cast<const uint32_t*>(info.in_data);
|
||||
|
||||
if (!(info.format == XYBitmap || info.in_depth == info.out_depth))
|
||||
{
|
||||
dwarnln("format {}, in depth {}, out depth {}", info.format, info.in_depth, info.out_depth);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
ASSERT(info.format == XYBitmap || info.in_depth == info.out_depth);
|
||||
|
||||
switch (info.format)
|
||||
{
|
||||
|
|
@ -86,3 +92,52 @@ void put_image(const PutImageInfo& info)
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void get_image(const GetImageInfo& info)
|
||||
{
|
||||
uint8_t out_bpp = 0;
|
||||
for (const auto& format : g_formats)
|
||||
if (format.depth == info.depth)
|
||||
out_bpp = format.bitsPerPixel;
|
||||
ASSERT(out_bpp && 32 % out_bpp == 0);
|
||||
|
||||
ASSERT(info.in_x >= 0 && info.in_y >= 0);
|
||||
ASSERT(info.in_x + info.w <= info.in_w);
|
||||
ASSERT(info.in_y + info.h <= info.in_h);
|
||||
|
||||
if (info.format != XYBitmap && info.format != ZPixmap)
|
||||
dwarnln("GetImage with format {}", info.format);
|
||||
|
||||
auto* out_data_u32 = static_cast<uint32_t*>(info.out_data);
|
||||
const auto* in_data_u32 = static_cast<const uint32_t*>(info.in_data);
|
||||
|
||||
if (out_bpp == 32)
|
||||
{
|
||||
for (int32_t y = 0; y < info.h; y++)
|
||||
{
|
||||
const size_t out_off = y * info.w;
|
||||
const size_t in_off = (info.in_y + y) * info.in_w + info.in_x;
|
||||
memcpy(&out_data_u32[out_off], &in_data_u32[in_off], info.w * 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto dwords_per_scanline = (info.w * out_bpp + 31) / 32;
|
||||
|
||||
memset(out_data_u32, 0, dwords_per_scanline * info.h * 4);
|
||||
|
||||
for (int32_t y = 0; y < info.h; y++)
|
||||
{
|
||||
const auto in_row_off = (info.in_y + y) * info.in_w + info.in_x;
|
||||
for (int32_t x = 0; x < info.w; x++)
|
||||
{
|
||||
const auto bit_offset = x * out_bpp;
|
||||
const auto dword = bit_offset / 32;
|
||||
const auto shift = bit_offset % 32;
|
||||
const auto mask = (1u << out_bpp) - 1;
|
||||
out_data_u32[dword] |= (in_data_u32[in_row_off + x] & mask) << shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct PutImageInfo
|
||||
{
|
||||
|
|
@ -25,4 +26,24 @@ struct PutImageInfo
|
|||
uint8_t format;
|
||||
};
|
||||
|
||||
struct GetImageInfo
|
||||
{
|
||||
void* out_data;
|
||||
|
||||
const void* in_data;
|
||||
int32_t in_x;
|
||||
int32_t in_y;
|
||||
uint32_t in_w;
|
||||
uint32_t in_h;
|
||||
|
||||
// out matches these dimensions
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
|
||||
uint8_t depth;
|
||||
uint8_t format;
|
||||
};
|
||||
|
||||
uint32_t image_dwords(uint32_t width, uint32_t height, uint8_t depth);
|
||||
void put_image(const PutImageInfo& info);
|
||||
void get_image(const GetImageInfo& info);
|
||||
|
|
|
|||
Loading…
Reference in New Issue