mirror of
https://github.com/hyprwm/hyprpicker.git
synced 2024-12-22 14:19:48 +01:00
Add support for 24 bit formats (#29)
This was the missing puzzle-piece for support for NVidia-GPUs
This commit is contained in:
parent
e4c267292a
commit
234c2da51a
4 changed files with 91 additions and 11 deletions
|
@ -301,7 +301,7 @@ void Events::handleBufferRelease(void *data, struct wl_buffer *wl_buffer) {
|
||||||
void Events::handleSCBuffer(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) {
|
void Events::handleSCBuffer(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) {
|
||||||
const auto PLS = (CLayerSurface*)data;
|
const auto PLS = (CLayerSurface*)data;
|
||||||
|
|
||||||
g_pHyprpicker->createBuffer(&PLS->screenBuffer, width, height, format);
|
g_pHyprpicker->createBuffer(&PLS->screenBuffer, width, height, format, stride);
|
||||||
|
|
||||||
zwlr_screencopy_frame_v1_copy(frame, PLS->screenBuffer.buffer);
|
zwlr_screencopy_frame_v1_copy(frame, PLS->screenBuffer.buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,12 @@ struct SPoolBuffer {
|
||||||
cairo_surface_t* surface = nullptr;
|
cairo_surface_t* surface = nullptr;
|
||||||
cairo_t* cairo = nullptr;
|
cairo_t* cairo = nullptr;
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
|
|
||||||
|
// malloc'ed buffer for 24bit formats
|
||||||
|
void* paddedData = nullptr;
|
||||||
|
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
uint32_t stride = 0;
|
||||||
Vector2D pixelSize;
|
Vector2D pixelSize;
|
||||||
|
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
|
|
|
@ -65,8 +65,8 @@ void CHyprpicker::recheckACK() {
|
||||||
zwlr_layer_surface_v1_ack_configure(ls->pLayerSurface, ls->ACKSerial);
|
zwlr_layer_surface_v1_ack_configure(ls->pLayerSurface, ls->ACKSerial);
|
||||||
|
|
||||||
if (!ls->buffers[0].buffer) {
|
if (!ls->buffers[0].buffer) {
|
||||||
createBuffer(&ls->buffers[0], ls->m_pMonitor->size.x * ls->m_pMonitor->scale, ls->m_pMonitor->size.y * ls->m_pMonitor->scale, WL_SHM_FORMAT_ARGB8888);
|
createBuffer(&ls->buffers[0], ls->m_pMonitor->size.x * ls->m_pMonitor->scale, ls->m_pMonitor->size.y * ls->m_pMonitor->scale, WL_SHM_FORMAT_ARGB8888, ls->m_pMonitor->size.x * ls->m_pMonitor->scale * 4);
|
||||||
createBuffer(&ls->buffers[1], ls->m_pMonitor->size.x * ls->m_pMonitor->scale, ls->m_pMonitor->size.y * ls->m_pMonitor->scale, WL_SHM_FORMAT_ARGB8888);
|
createBuffer(&ls->buffers[1], ls->m_pMonitor->size.x * ls->m_pMonitor->scale, ls->m_pMonitor->size.y * ls->m_pMonitor->scale, WL_SHM_FORMAT_ARGB8888, ls->m_pMonitor->size.x * ls->m_pMonitor->scale * 4);
|
||||||
|
|
||||||
int XCURSOR_SIZE = 24;
|
int XCURSOR_SIZE = 24;
|
||||||
if (getenv("XCURSOR_SIZE")) {
|
if (getenv("XCURSOR_SIZE")) {
|
||||||
|
@ -155,9 +155,8 @@ int CHyprpicker::createPoolFile(size_t size, std::string& name) {
|
||||||
return FD;
|
return FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprpicker::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint32_t format) {
|
void CHyprpicker::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint32_t format, uint32_t stride) {
|
||||||
const uint STRIDE = w * 4;
|
const size_t SIZE = stride * h;
|
||||||
const size_t SIZE = STRIDE * h;
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
const auto FD = createPoolFile(SIZE, name);
|
const auto FD = createPoolFile(SIZE, name);
|
||||||
|
@ -169,7 +168,7 @@ void CHyprpicker::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint3
|
||||||
|
|
||||||
const auto DATA = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, FD, 0);
|
const auto DATA = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, FD, 0);
|
||||||
const auto POOL = wl_shm_create_pool(g_pHyprpicker->m_pWLSHM, FD, SIZE);
|
const auto POOL = wl_shm_create_pool(g_pHyprpicker->m_pWLSHM, FD, SIZE);
|
||||||
pBuffer->buffer = wl_shm_pool_create_buffer(POOL, 0, w, h, STRIDE, format);
|
pBuffer->buffer = wl_shm_pool_create_buffer(POOL, 0, w, h, stride, format);
|
||||||
|
|
||||||
wl_buffer_add_listener(pBuffer->buffer, &Events::bufferListener, pBuffer);
|
wl_buffer_add_listener(pBuffer->buffer, &Events::bufferListener, pBuffer);
|
||||||
|
|
||||||
|
@ -182,6 +181,7 @@ void CHyprpicker::createBuffer(SPoolBuffer* pBuffer, int32_t w, int32_t h, uint3
|
||||||
pBuffer->data = DATA;
|
pBuffer->data = DATA;
|
||||||
pBuffer->pixelSize = Vector2D(w, h);
|
pBuffer->pixelSize = Vector2D(w, h);
|
||||||
pBuffer->name = name;
|
pBuffer->name = name;
|
||||||
|
pBuffer->stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprpicker::destroyBuffer(SPoolBuffer* pBuffer) {
|
void CHyprpicker::destroyBuffer(SPoolBuffer* pBuffer) {
|
||||||
|
@ -195,6 +195,10 @@ void CHyprpicker::destroyBuffer(SPoolBuffer* pBuffer) {
|
||||||
pBuffer->surface = nullptr;
|
pBuffer->surface = nullptr;
|
||||||
|
|
||||||
unlink(pBuffer->name.c_str());
|
unlink(pBuffer->name.c_str());
|
||||||
|
|
||||||
|
if (pBuffer->paddedData) {
|
||||||
|
free(pBuffer->paddedData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprpicker::createSeat(wl_seat* pSeat) {
|
void CHyprpicker::createSeat(wl_seat* pSeat) {
|
||||||
|
@ -231,6 +235,63 @@ void CHyprpicker::convertBuffer(SPoolBuffer* pBuffer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mallocs a new buffer, which needs to be free'd!
|
||||||
|
void* convert24To32Buffer(SPoolBuffer* pBuffer) {
|
||||||
|
uint8_t* newBuffer = (uint8_t*)malloc((size_t)pBuffer->pixelSize.x * pBuffer->pixelSize.y * 4);
|
||||||
|
int newBufferStride = pBuffer->pixelSize.x * 4;
|
||||||
|
uint8_t* oldBuffer = (uint8_t*)pBuffer->data;
|
||||||
|
|
||||||
|
switch (pBuffer->format) {
|
||||||
|
case WL_SHM_FORMAT_BGR888: {
|
||||||
|
for (int y = 0; y < pBuffer->pixelSize.y; ++y) {
|
||||||
|
for (int x = 0; x < pBuffer->pixelSize.x; ++x) {
|
||||||
|
struct pixel3 {
|
||||||
|
// little-endian RGB
|
||||||
|
unsigned char blue;
|
||||||
|
unsigned char green;
|
||||||
|
unsigned char red;
|
||||||
|
}* srcPx = (struct pixel3*)(oldBuffer + y * pBuffer->stride + x * 3);
|
||||||
|
struct pixel4 {
|
||||||
|
// little-endian ARGB
|
||||||
|
unsigned char blue;
|
||||||
|
unsigned char green;
|
||||||
|
unsigned char red;
|
||||||
|
unsigned char alpha;
|
||||||
|
}* dstPx = (struct pixel4*)(newBuffer + y * newBufferStride + x * 4);
|
||||||
|
*dstPx = {srcPx->red, srcPx->green, srcPx->blue, 0xFF};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WL_SHM_FORMAT_RGB888: {
|
||||||
|
for (int y = 0; y < pBuffer->pixelSize.y; ++y) {
|
||||||
|
for (int x = 0; x < pBuffer->pixelSize.x; ++x) {
|
||||||
|
struct pixel3 {
|
||||||
|
// big-endian RGB
|
||||||
|
unsigned char red;
|
||||||
|
unsigned char green;
|
||||||
|
unsigned char blue;
|
||||||
|
}* srcPx = (struct pixel3*)(oldBuffer + y * pBuffer->stride + x * 3);
|
||||||
|
struct pixel4 {
|
||||||
|
// big-endian ARGB
|
||||||
|
unsigned char alpha;
|
||||||
|
unsigned char red;
|
||||||
|
unsigned char green;
|
||||||
|
unsigned char blue;
|
||||||
|
}* dstPx = (struct pixel4*)(newBuffer + y * newBufferStride + x * 4);
|
||||||
|
*dstPx = {0xFF, srcPx->red, srcPx->green, srcPx->blue};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
Debug::log(CRIT, "Unsupported format for 24bit buffer %i", pBuffer->format);
|
||||||
|
}
|
||||||
|
g_pHyprpicker->finish(1);
|
||||||
|
}
|
||||||
|
return newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) {
|
void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) {
|
||||||
const auto PBUFFER = getBufferForLS(pSurface);
|
const auto PBUFFER = getBufferForLS(pSurface);
|
||||||
|
|
||||||
|
@ -238,8 +299,21 @@ void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!pSurface->screenBuffer.surface) {
|
if (!pSurface->screenBuffer.surface) {
|
||||||
convertBuffer(&pSurface->screenBuffer);
|
int bytesPerPixel = pSurface->screenBuffer.stride / (int)pSurface->screenBuffer.pixelSize.x;
|
||||||
pSurface->screenBuffer.surface = cairo_image_surface_create_for_data((unsigned char*)pSurface->screenBuffer.data, CAIRO_FORMAT_ARGB32, pSurface->screenBuffer.pixelSize.x, pSurface->screenBuffer.pixelSize.y, pSurface->screenBuffer.pixelSize.x * 4);
|
void* data = pSurface->screenBuffer.data;
|
||||||
|
if (bytesPerPixel == 4) {
|
||||||
|
convertBuffer(&pSurface->screenBuffer);
|
||||||
|
}
|
||||||
|
else if (bytesPerPixel == 3) {
|
||||||
|
Debug::log(WARN, "24 bit formats are unsupported, hyprpicker may or may not work as intended!");
|
||||||
|
data = convert24To32Buffer(&pSurface->screenBuffer);
|
||||||
|
pSurface->screenBuffer.paddedData = data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Debug::log(CRIT, "Unsupported stride/bytes per pixel %i", bytesPerPixel);
|
||||||
|
g_pHyprpicker->finish(1);
|
||||||
|
}
|
||||||
|
pSurface->screenBuffer.surface = cairo_image_surface_create_for_data((unsigned char*)data, CAIRO_FORMAT_ARGB32, pSurface->screenBuffer.pixelSize.x, pSurface->screenBuffer.pixelSize.y, pSurface->screenBuffer.pixelSize.x * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
PBUFFER->surface = cairo_image_surface_create_for_data((unsigned char*)PBUFFER->data, CAIRO_FORMAT_ARGB32, pSurface->m_pMonitor->size.x * pSurface->m_pMonitor->scale, pSurface->m_pMonitor->size.y * pSurface->m_pMonitor->scale, PBUFFER->pixelSize.x * 4);
|
PBUFFER->surface = cairo_image_surface_create_for_data((unsigned char*)PBUFFER->data, CAIRO_FORMAT_ARGB32, pSurface->m_pMonitor->size.x * pSurface->m_pMonitor->scale, pSurface->m_pMonitor->size.y * pSurface->m_pMonitor->scale, PBUFFER->pixelSize.x * 4);
|
||||||
|
@ -350,12 +424,13 @@ void CHyprpicker::sendFrame(CLayerSurface* pSurface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CColor CHyprpicker::getColorFromPixel(CLayerSurface* pLS, Vector2D pix) {
|
CColor CHyprpicker::getColorFromPixel(CLayerSurface* pLS, Vector2D pix) {
|
||||||
|
void* dataSrc = pLS->screenBuffer.paddedData ? pLS->screenBuffer.paddedData : pLS->screenBuffer.data;
|
||||||
struct pixel {
|
struct pixel {
|
||||||
unsigned char blue;
|
unsigned char blue;
|
||||||
unsigned char green;
|
unsigned char green;
|
||||||
unsigned char red;
|
unsigned char red;
|
||||||
unsigned char alpha;
|
unsigned char alpha;
|
||||||
}* px = (struct pixel*)((char*)pLS->screenBuffer.data + (int)pix.y * (int)pLS->screenBuffer.pixelSize.x * 4 + (int)pix.x * 4);
|
}* px = (struct pixel*)((char*)dataSrc + (int)pix.y * (int)pLS->screenBuffer.pixelSize.x * 4 + (int)pix.x * 4);
|
||||||
|
|
||||||
return CColor{(uint8_t)px->red, (uint8_t)px->green, (uint8_t)px->blue, (uint8_t)px->alpha};
|
return CColor{(uint8_t)px->red, (uint8_t)px->green, (uint8_t)px->blue, (uint8_t)px->alpha};
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
|
|
||||||
void renderSurface(CLayerSurface*, bool forceInactive = false);
|
void renderSurface(CLayerSurface*, bool forceInactive = false);
|
||||||
|
|
||||||
void createBuffer(SPoolBuffer*, int32_t, int32_t, uint32_t);
|
void createBuffer(SPoolBuffer*, int32_t, int32_t, uint32_t, uint32_t);
|
||||||
void destroyBuffer(SPoolBuffer*);
|
void destroyBuffer(SPoolBuffer*);
|
||||||
int createPoolFile(size_t, std::string&);
|
int createPoolFile(size_t, std::string&);
|
||||||
bool setCloexec(const int&);
|
bool setCloexec(const int&);
|
||||||
|
|
Loading…
Reference in a new issue