Skip to content

Commit

Permalink
renderer: use cairo for cpu buffer rendering (#9071)
Browse files Browse the repository at this point in the history
Instead of a wonky memcpy which doesn't work when anything non-standard is used (size, pos, transform), just use cairo
  • Loading branch information
vaxerski authored Jan 16, 2025
1 parent 52b9ae5 commit 0dc7367
Showing 1 changed file with 51 additions and 7 deletions.
58 changes: 51 additions & 7 deletions src/managers/PointerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "SeatManager.hpp"
#include <cstring>
#include <gbm.h>
#include <cairo/cairo.h>

CPointerManager::CPointerManager() {
hooks.monitorAdded = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any data) {
Expand Down Expand Up @@ -481,15 +482,58 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager

// then, we just yeet it into the dumb buffer

const auto DMABUF = buf->dmabuf();
auto [data, fmt, size] = buf->beginDataPtr(0);

memset(data, 0, size);
if (buf->dmabuf().size.x > texture->m_vSize.x) {
size_t STRIDE = 4 * texture->m_vSize.x;
for (int i = 0; i < texture->m_vSize.y; i++)
memcpy(data + i * buf->dmabuf().strides[0], texData.data() + i * STRIDE, STRIDE);
} else
memcpy(data, texData.data(), std::min(size, texData.size()));
auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, DMABUF.size.x, DMABUF.size.y);
auto CAIRODATASURFACE =
cairo_image_surface_create_for_data((unsigned char*)texData.data(), CAIRO_FORMAT_ARGB32, texture->m_vSize.x, texture->m_vSize.y, texture->m_vSize.x * 4);

auto CAIRO = cairo_create(CAIROSURFACE);

cairo_set_operator(CAIRO, CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba(CAIRO, 0, 0, 0, 0);
cairo_rectangle(CAIRO, 0, 0, texture->m_vSize.x, texture->m_vSize.y);
cairo_fill(CAIRO);

const auto PATTERNPRE = cairo_pattern_create_for_surface(CAIRODATASURFACE);
cairo_pattern_set_filter(PATTERNPRE, CAIRO_FILTER_BILINEAR);
cairo_matrix_t matrixPre;
cairo_matrix_init_identity(&matrixPre);

const auto TR = state->monitor->transform;

if (TR) {
cairo_matrix_rotate(&matrixPre, M_PI_2 * (double)TR);

// FIXME: this is wrong, and doesnt work for 5, 6 and 7. (flipped + rot)
// cba to do it rn, does anyone fucking use that??
if (TR >= WL_OUTPUT_TRANSFORM_FLIPPED) {
cairo_matrix_scale(&matrixPre, -1, 1);
cairo_matrix_translate(&matrixPre, -DMABUF.size.x, 0);
}

if (TR == 3 || TR == 7)
cairo_matrix_translate(&matrixPre, -DMABUF.size.x, 0);
else if (TR == 2 || TR == 6)
cairo_matrix_translate(&matrixPre, -DMABUF.size.x, -DMABUF.size.y);
else if (TR == 1 || TR == 5)
cairo_matrix_translate(&matrixPre, 0, -DMABUF.size.y);
}

cairo_pattern_set_matrix(PATTERNPRE, &matrixPre);
cairo_set_source(CAIRO, PATTERNPRE);
cairo_paint(CAIRO);

cairo_surface_flush(CAIROSURFACE);

cairo_pattern_destroy(PATTERNPRE);

memcpy(data, cairo_image_surface_get_data(CAIROSURFACE), (size_t)cairo_image_surface_get_height(CAIROSURFACE) * cairo_image_surface_get_stride(CAIROSURFACE));

cairo_destroy(CAIRO);
cairo_surface_destroy(CAIROSURFACE);
cairo_surface_destroy(CAIRODATASURFACE);

buf->endDataPtr();

Expand Down

0 comments on commit 0dc7367

Please sign in to comment.