mirror of
https://github.com/hyprwm/hyprpicker.git
synced 2024-12-22 06:09:48 +01:00
internal: transform received screencopy buffer
This commit is contained in:
parent
0889bd5f6f
commit
03bc27be94
5 changed files with 123 additions and 51 deletions
|
@ -4,7 +4,9 @@
|
|||
|
||||
void Events::geometry(void* data, wl_output* output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char* make, const char* model,
|
||||
int32_t transform) {
|
||||
// ignored
|
||||
const auto PMONITOR = (SMonitor*)data;
|
||||
|
||||
PMONITOR->transform = (wl_output_transform)transform;
|
||||
}
|
||||
|
||||
void Events::mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
||||
|
@ -38,9 +40,10 @@ void Events::ls_configure(void* data, zwlr_layer_surface_v1* surface, uint32_t s
|
|||
const auto PLAYERSURFACE = (CLayerSurface*)data;
|
||||
|
||||
PLAYERSURFACE->m_pMonitor->size = Vector2D(width, height);
|
||||
PLAYERSURFACE->ACKSerial = serial;
|
||||
PLAYERSURFACE->wantsACK = true;
|
||||
PLAYERSURFACE->working = true;
|
||||
|
||||
PLAYERSURFACE->ACKSerial = serial;
|
||||
PLAYERSURFACE->wantsACK = true;
|
||||
PLAYERSURFACE->working = true;
|
||||
|
||||
g_pHyprpicker->recheckACK();
|
||||
}
|
||||
|
@ -276,6 +279,8 @@ 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) {
|
||||
const auto PLS = (CLayerSurface*)data;
|
||||
|
||||
PLS->screenBufferFormat = format;
|
||||
|
||||
if (!PLS->screenBuffer.buffer)
|
||||
g_pHyprpicker->createBuffer(&PLS->screenBuffer, width, height, format, stride);
|
||||
|
||||
|
@ -288,12 +293,91 @@ void Events::handleSCFlags(void* data, struct zwlr_screencopy_frame_v1* frame, u
|
|||
PLS->scflags = flags;
|
||||
|
||||
g_pHyprpicker->recheckACK();
|
||||
|
||||
g_pHyprpicker->renderSurface(PLS);
|
||||
}
|
||||
|
||||
void Events::handleSCReady(void* data, struct zwlr_screencopy_frame_v1* frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
|
||||
// ignore
|
||||
void Events::handleSCReady(void* lsdata, struct zwlr_screencopy_frame_v1* frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
|
||||
const auto PLS = (CLayerSurface*)lsdata;
|
||||
|
||||
SPoolBuffer newBuf;
|
||||
Vector2D transformedSize = PLS->screenBuffer.pixelSize;
|
||||
|
||||
if (PLS->m_pMonitor->transform % 2 == 1)
|
||||
std::swap(transformedSize.x, transformedSize.y);
|
||||
|
||||
g_pHyprpicker->createBuffer(&newBuf, transformedSize.x, transformedSize.y, PLS->screenBufferFormat, transformedSize.x * 4);
|
||||
|
||||
int bytesPerPixel = PLS->screenBuffer.stride / (int)PLS->screenBuffer.pixelSize.x;
|
||||
void* data = PLS->screenBuffer.data;
|
||||
if (bytesPerPixel == 4)
|
||||
g_pHyprpicker->convertBuffer(&PLS->screenBuffer);
|
||||
else if (bytesPerPixel == 3) {
|
||||
Debug::log(WARN, "24 bit formats are unsupported, hyprpicker may or may not work as intended!");
|
||||
data = g_pHyprpicker->convert24To32Buffer(&PLS->screenBuffer);
|
||||
PLS->screenBuffer.paddedData = data;
|
||||
} else {
|
||||
Debug::log(CRIT, "Unsupported stride/bytes per pixel %i", bytesPerPixel);
|
||||
g_pHyprpicker->finish(1);
|
||||
}
|
||||
|
||||
cairo_surface_t* oldSurface = cairo_image_surface_create_for_data((unsigned char*)data, CAIRO_FORMAT_ARGB32, PLS->screenBuffer.pixelSize.x, PLS->screenBuffer.pixelSize.y,
|
||||
PLS->screenBuffer.pixelSize.x * 4);
|
||||
|
||||
cairo_surface_flush(oldSurface);
|
||||
|
||||
newBuf.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, transformedSize.x, transformedSize.y);
|
||||
|
||||
const auto PCAIRO = cairo_create(newBuf.surface);
|
||||
|
||||
auto cairoTransformMtx = [&](cairo_matrix_t* mtx) -> void {
|
||||
const auto TR = PLS->m_pMonitor->transform % 4;
|
||||
|
||||
if (TR == 0)
|
||||
return;
|
||||
|
||||
const auto TRFLIP = PLS->m_pMonitor->transform >= 4;
|
||||
|
||||
cairo_matrix_rotate(mtx, -M_PI_2 * (double)TR);
|
||||
|
||||
if (TR == 1)
|
||||
cairo_matrix_translate(mtx, -transformedSize.x, 0);
|
||||
else if (TR == 2)
|
||||
cairo_matrix_translate(mtx, -transformedSize.x, -transformedSize.y);
|
||||
else if (TR == 3)
|
||||
cairo_matrix_translate(mtx, 0, -transformedSize.y);
|
||||
|
||||
// TODO: flipped
|
||||
};
|
||||
|
||||
cairo_save(PCAIRO);
|
||||
|
||||
cairo_set_source_rgba(PCAIRO, 0, 0, 0, 0);
|
||||
|
||||
cairo_rectangle(PCAIRO, 0, 0, 0xFFFF, 0xFFFF);
|
||||
cairo_fill(PCAIRO);
|
||||
|
||||
const auto PATTERNPRE = cairo_pattern_create_for_surface(oldSurface);
|
||||
cairo_pattern_set_filter(PATTERNPRE, CAIRO_FILTER_BILINEAR);
|
||||
cairo_matrix_t matrixPre;
|
||||
cairo_matrix_init_identity(&matrixPre);
|
||||
cairo_matrix_scale(&matrixPre, 1.0, 1.0);
|
||||
cairoTransformMtx(&matrixPre);
|
||||
cairo_pattern_set_matrix(PATTERNPRE, &matrixPre);
|
||||
cairo_set_source(PCAIRO, PATTERNPRE);
|
||||
cairo_paint(PCAIRO);
|
||||
|
||||
cairo_surface_flush(newBuf.surface);
|
||||
|
||||
cairo_pattern_destroy(PATTERNPRE);
|
||||
|
||||
cairo_destroy(PCAIRO);
|
||||
|
||||
cairo_surface_destroy(oldSurface);
|
||||
|
||||
g_pHyprpicker->destroyBuffer(&PLS->screenBuffer);
|
||||
|
||||
PLS->screenBuffer = newBuf;
|
||||
|
||||
g_pHyprpicker->renderSurface(PLS);
|
||||
}
|
||||
|
||||
void Events::handleSCFailed(void* data, struct zwlr_screencopy_frame_v1* frame) {
|
||||
|
|
|
@ -6,31 +6,32 @@
|
|||
struct SMonitor;
|
||||
|
||||
class CLayerSurface {
|
||||
public:
|
||||
public:
|
||||
CLayerSurface(SMonitor*);
|
||||
~CLayerSurface();
|
||||
|
||||
SMonitor* m_pMonitor = nullptr;
|
||||
SMonitor* m_pMonitor = nullptr;
|
||||
|
||||
zwlr_layer_surface_v1* pLayerSurface = nullptr;
|
||||
wl_surface* pSurface = nullptr;
|
||||
wl_surface* pCursorSurface = nullptr;
|
||||
zwlr_layer_surface_v1* pLayerSurface = nullptr;
|
||||
wl_surface* pSurface = nullptr;
|
||||
wl_surface* pCursorSurface = nullptr;
|
||||
|
||||
bool wantsACK = false;
|
||||
uint32_t ACKSerial = 0;
|
||||
bool working = false;
|
||||
bool wantsACK = false;
|
||||
uint32_t ACKSerial = 0;
|
||||
bool working = false;
|
||||
|
||||
int lastBuffer = 0;
|
||||
SPoolBuffer buffers[2];
|
||||
|
||||
SPoolBuffer screenBuffer;
|
||||
uint32_t scflags = 0;
|
||||
int lastBuffer = 0;
|
||||
SPoolBuffer buffers[2];
|
||||
|
||||
bool dirty = true;
|
||||
SPoolBuffer screenBuffer;
|
||||
uint32_t scflags = 0;
|
||||
uint32_t screenBufferFormat = 0;
|
||||
|
||||
bool rendered = false;
|
||||
bool dirty = true;
|
||||
|
||||
wl_callback* frame_callback = nullptr;
|
||||
bool rendered = false;
|
||||
|
||||
wl_cursor_image* pCursorImg = nullptr;
|
||||
wl_callback* frame_callback = nullptr;
|
||||
|
||||
wl_cursor_image* pCursorImg = nullptr;
|
||||
};
|
|
@ -3,13 +3,14 @@
|
|||
#include "../defines.hpp"
|
||||
|
||||
struct SMonitor {
|
||||
std::string name = "";
|
||||
wl_output* output = nullptr;
|
||||
uint32_t wayland_name = 0;
|
||||
Vector2D size;
|
||||
int scale;
|
||||
std::string name = "";
|
||||
wl_output* output = nullptr;
|
||||
uint32_t wayland_name = 0;
|
||||
Vector2D size;
|
||||
int scale;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
bool ready = false;
|
||||
bool ready = false;
|
||||
|
||||
zwlr_screencopy_frame_v1* pSCFrame = nullptr;
|
||||
};
|
|
@ -238,7 +238,7 @@ void CHyprpicker::convertBuffer(SPoolBuffer* pBuffer) {
|
|||
}
|
||||
|
||||
// Mallocs a new buffer, which needs to be free'd!
|
||||
void* convert24To32Buffer(SPoolBuffer* pBuffer) {
|
||||
void* CHyprpicker::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;
|
||||
|
@ -298,32 +298,17 @@ void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) {
|
|||
if (!PBUFFER || !pSurface->screenBuffer.buffer)
|
||||
return;
|
||||
|
||||
if (!pSurface->screenBuffer.surface) {
|
||||
int bytesPerPixel = pSurface->screenBuffer.stride / (int)pSurface->screenBuffer.pixelSize.x;
|
||||
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->cairo = cairo_create(PBUFFER->surface);
|
||||
|
||||
PBUFFER->cairo = cairo_create(PBUFFER->surface);
|
||||
|
||||
const auto PCAIRO = PBUFFER->cairo;
|
||||
|
||||
cairo_save(PCAIRO);
|
||||
|
||||
cairo_set_source_rgba(PCAIRO, 0, 0, 0, 0);
|
||||
|
||||
cairo_rectangle(PCAIRO, 0, 0, pSurface->m_pMonitor->size.x * pSurface->m_pMonitor->scale, pSurface->m_pMonitor->size.y * pSurface->m_pMonitor->scale);
|
||||
cairo_fill(PCAIRO);
|
||||
|
||||
|
@ -433,7 +418,7 @@ void CHyprpicker::sendFrame(CLayerSurface* pSurface) {
|
|||
|
||||
wl_surface_attach(pSurface->pSurface, pSurface->lastBuffer == 0 ? pSurface->buffers[0].buffer : pSurface->buffers[1].buffer, 0, 0);
|
||||
wl_surface_set_buffer_scale(pSurface->pSurface, pSurface->m_pMonitor->scale);
|
||||
wl_surface_damage_buffer(pSurface->pSurface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_damage_buffer(pSurface->pSurface, 0, 0, 0xFFFF, 0xFFFF);
|
||||
wl_surface_commit(pSurface->pSurface);
|
||||
|
||||
pSurface->dirty = false;
|
||||
|
|
|
@ -58,6 +58,7 @@ class CHyprpicker {
|
|||
SPoolBuffer* getBufferForLS(CLayerSurface*);
|
||||
|
||||
void convertBuffer(SPoolBuffer*);
|
||||
void* convert24To32Buffer(SPoolBuffer*);
|
||||
|
||||
void markDirty();
|
||||
|
||||
|
|
Loading…
Reference in a new issue