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);
|
dprintln(" planeMask: {}", request.planeMask);
|
||||||
|
|
||||||
auto& object = *g_objects[request.drawable];
|
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;
|
const auto dwords = image_dwords(request.width, request.height, in_depth);
|
||||||
for (const auto& format : g_formats)
|
|
||||||
if (format.depth == out_depth)
|
|
||||||
bpp = format.bitsPerPixel;
|
|
||||||
ASSERT(bpp && 32 % bpp == 0);
|
|
||||||
|
|
||||||
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 {
|
xGetImageReply reply {
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
.depth = out_depth,
|
.depth = in_depth,
|
||||||
.sequenceNumber = client_info.sequence,
|
.sequenceNumber = client_info.sequence,
|
||||||
.length = length,
|
.length = dwords,
|
||||||
.visual = g_visual.visualID,
|
.visual = g_visual.visualID,
|
||||||
};
|
};
|
||||||
TRY(encode(client_info.output_buffer, reply));
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
if (request.format != ZPixmap)
|
const auto old_size = client_info.output_buffer.size();
|
||||||
dwarnln("GetImage with format {}", request.format);
|
TRY(client_info.output_buffer.resize(old_size + dwords * 4));
|
||||||
|
|
||||||
if (bpp == 32)
|
auto* out_data = client_info.output_buffer.data() + old_size;
|
||||||
{
|
|
||||||
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));
|
|
||||||
|
|
||||||
for (int32_t y = 0; y < request.height; y++)
|
get_image({
|
||||||
{
|
.out_data = out_data,
|
||||||
for (auto& dword : scanline)
|
.in_data = in_data.data(),
|
||||||
dword = 0;
|
.in_x = request.x,
|
||||||
|
.in_y = request.y,
|
||||||
const auto row_off = (request.y + y) * out_w;
|
.in_w = in_w,
|
||||||
for (int32_t x = 0; x < request.width; x++)
|
.in_h = in_h,
|
||||||
{
|
.w = request.width,
|
||||||
const auto bit_offset = x * bpp;
|
.h = request.height,
|
||||||
const auto dword = bit_offset / 32;
|
.depth = in_depth,
|
||||||
const auto shift = bit_offset % 32;
|
.format = request.format,
|
||||||
const auto mask = (1u << bpp) - 1;
|
});
|
||||||
scanline[dword] |= (out_data[row_off + (request.x + x)] & mask) << shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(encode(client_info.output_buffer, scanline));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,18 @@ set(SOURCES
|
||||||
Extensions.cpp
|
Extensions.cpp
|
||||||
ExtBigReg.cpp
|
ExtBigReg.cpp
|
||||||
ExtRANDR.cpp
|
ExtRANDR.cpp
|
||||||
ExtSHM.cpp
|
|
||||||
Image.cpp
|
Image.cpp
|
||||||
Keymap.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})
|
add_executable(xbanan ${SOURCES})
|
||||||
banan_link_library(xbanan ban)
|
banan_link_library(xbanan ban)
|
||||||
banan_link_library(xbanan libgui)
|
banan_link_library(xbanan libgui)
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,53 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
||||||
|
|
||||||
break;
|
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:
|
default:
|
||||||
dwarnln("unsupported shm minor opcode {}", packet[1]);
|
dwarnln("unsupported shm minor opcode {}", packet[1]);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,16 @@
|
||||||
|
|
||||||
#include <X11/X.h>
|
#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)
|
void put_image(const PutImageInfo& info)
|
||||||
{
|
{
|
||||||
uint8_t in_bpp = 0;
|
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);
|
auto* out_data_u32 = static_cast<uint32_t*>(info.out_data);
|
||||||
const auto* in_data_u32 = static_cast<const uint32_t*>(info.in_data);
|
const auto* in_data_u32 = static_cast<const uint32_t*>(info.in_data);
|
||||||
|
|
||||||
if (!(info.format == XYBitmap || info.in_depth == info.out_depth))
|
ASSERT(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();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (info.format)
|
switch (info.format)
|
||||||
{
|
{
|
||||||
|
|
@ -86,3 +92,52 @@ void put_image(const PutImageInfo& info)
|
||||||
ASSERT_NOT_REACHED();
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct PutImageInfo
|
struct PutImageInfo
|
||||||
{
|
{
|
||||||
|
|
@ -25,4 +26,24 @@ struct PutImageInfo
|
||||||
uint8_t format;
|
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 put_image(const PutImageInfo& info);
|
||||||
|
void get_image(const GetImageInfo& info);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue