Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 61 additions & 35 deletions src/external/rlsw.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,6 @@ SWAPI void swClose(void);
SWAPI bool swResizeFramebuffer(int w, int h);
SWAPI void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels);
SWAPI void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels);
SWAPI void *swGetColorBuffer(int *w, int *h);

SWAPI void swEnable(SWstate state);
SWAPI void swDisable(SWstate state);
Expand Down Expand Up @@ -616,12 +615,23 @@ SWAPI void swBindTexture(uint32_t id);
#include <math.h> // Required for: floorf(), fabsf()

#if defined(_MSC_VER)
#define ALIGNAS(x) __declspec(align(x))
#define SW_ALIGN(x) __declspec(align(x))
#elif defined(__GNUC__) || defined(__clang__)
#define ALIGNAS(x) __attribute__((aligned(x)))
#define SW_ALIGN(x) __attribute__((aligned(x)))
#else
#include <stdalign.h>
#define ALIGNAS(x) alignas(x)
#define SW_ALIGN(x) // Do nothing if not available
#endif

#if defined(_M_X64) || defined(__x86_64__)
#define SW_ARCH_X86_64
#elif defined(_M_IX86) || defined(__i386__)
#define SW_ARCH_X86
#elif defined(_M_ARM) || defined(__arm__)
#define SW_ARCH_ARM32
#elif defined(_M_ARM64) || defined(__aarch64__)
#define SW_ARCH_ARM64
#elif defined(__riscv)
#define SW_ARCH_RISCV
#endif

#if defined(__FMA__) && defined(__AVX2__)
Expand Down Expand Up @@ -696,8 +706,15 @@ SWAPI void swBindTexture(uint32_t id);
#define SW_DEG2RAD (SW_PI/180.0f)
#define SW_RAD2DEG (180.0f/SW_PI)

#define SW_COLOR_PIXEL_SIZE 4 //(SW_COLOR_BUFFER_BITS >> 3)
#define SW_COLOR_PIXEL_SIZE (SW_COLOR_BUFFER_BITS >> 3)
#define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS >> 3)
#define SW_PIXEL_SIZE (SW_COLOR_PIXEL_SIZE + SW_DEPTH_PIXEL_SIZE)

#if (SW_PIXEL_SIZE <= 4)
#define SW_PIXEL_ALIGNMENT 4
#else // if (SW_PIXEL_SIZE <= 8)
#define SW_PIXEL_ALIGNMENT 8
#endif

#if (SW_COLOR_BUFFER_BITS == 8)
#define SW_COLOR_TYPE uint8_t
Expand Down Expand Up @@ -827,10 +844,12 @@ typedef struct {
} sw_texture_t;

// Pixel data type
// WARNING: ALIGNAS() macro requires a constant value (not operand)
typedef ALIGNAS(SW_COLOR_PIXEL_SIZE) struct {
typedef SW_ALIGN(SW_PIXEL_ALIGNMENT) struct {
SW_COLOR_TYPE color[SW_COLOR_PACK_COMP];
SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP];
#if (SW_PIXEL_SIZE % SW_PIXEL_ALIGNMENT != 0)
uint8_t padding[SW_PIXEL_ALIGNMENT - SW_PIXEL_SIZE % SW_PIXEL_ALIGNMENT];
#endif
} sw_pixel_t;

typedef struct {
Expand Down Expand Up @@ -2624,25 +2643,38 @@ static inline void sw_quad_clip_and_project(void)

static inline bool sw_quad_is_axis_aligned(void)
{
int horizontal = 0;
int vertical = 0;

// Reject quads with perspective projection
// The fast path assumes affine (non-perspective) quads,
// so we require all vertices to have homogeneous w = 1.0
for (int i = 0; i < 4; i++)
{
if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;

const float *v0 = RLSW.vertexBuffer[i].position;
const float *v1 = RLSW.vertexBuffer[(i + 1)%4].position;

float dx = v1[0] - v0[0];
float dy = v1[1] - v0[1];

if ((fabsf(dx) > 1e-6f) && (fabsf(dy) < 1e-6f)) horizontal++;
else if ((fabsf(dy) > 1e-6f) && (fabsf(dx) < 1e-6f)) vertical++;
else return false; // Diagonal edge -> not axis-aligned
}

return ((horizontal == 2) && (vertical == 2));
// Epsilon tolerance in screen space (pixels)
const float epsilon = 0.5f;

// Fetch screen-space positions for the four quad vertices
const float *p0 = RLSW.vertexBuffer[0].screen;
const float *p1 = RLSW.vertexBuffer[1].screen;
const float *p2 = RLSW.vertexBuffer[2].screen;
const float *p3 = RLSW.vertexBuffer[3].screen;

// Compute edge vectors between consecutive vertices
// These define the four sides of the quad in screen space
float dx01 = p1[0] - p0[0], dy01 = p1[1] - p0[1];
float dx12 = p2[0] - p1[0], dy12 = p2[1] - p1[1];
float dx23 = p3[0] - p2[0], dy23 = p3[1] - p2[1];
float dx30 = p0[0] - p3[0], dy30 = p0[1] - p3[1];

// Each edge must be either horizontal or vertical within epsilon tolerance
// If any edge deviates significantly from either axis, the quad is not axis-aligned
if (!((fabsf(dy01) < epsilon) || (fabsf(dx01) < epsilon))) return false;
if (!((fabsf(dy12) < epsilon) || (fabsf(dx12) < epsilon))) return false;
if (!((fabsf(dy23) < epsilon) || (fabsf(dx23) < epsilon))) return false;
if (!((fabsf(dy30) < epsilon) || (fabsf(dx30) < epsilon))) return false;

return true;
}

static inline void sw_quad_sort_cw(const sw_vertex_t* *output)
Expand Down Expand Up @@ -3660,11 +3692,6 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr
{
sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type);

if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc)
{
swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels);
}

if (wSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
if (hSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }

Expand All @@ -3674,6 +3701,13 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr
xSrc = sw_clampi(xSrc, 0, wSrc);
ySrc = sw_clampi(ySrc, 0, hSrc);

// Check if the sizes are identical after clamping the source to avoid unexpected issues
// REVIEW: This repeats the operations if true, so we could make a copy function without these checks
if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc)
{
swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels);
}

switch (pFormat)
{
case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
Expand All @@ -3696,14 +3730,6 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr
}
}

void *swGetColorBuffer(int *w, int *h)
{
if (w) *w = RLSW.framebuffer.width;
if (h) *h = RLSW.framebuffer.height;

return (void *)RLSW.framebuffer.pixels->color;
}

void swEnable(SWstate state)
{
switch (state)
Expand Down
21 changes: 2 additions & 19 deletions src/platforms/rcore_drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,15 +824,6 @@ void SwapScreenBuffer(void)
return;
}

// Get the software rendered color buffer
int bufferWidth = 0, bufferHeight = 0;
void *colorBuffer = swGetColorBuffer(&bufferWidth, &bufferHeight);
if (!colorBuffer)
{
TRACELOG(LOG_ERROR, "DISPLAY: Failed to get software color buffer");
return;
}

// Retrieving the dimensions of the display mode used
drmModeModeInfo *mode = &platform.connector->modes[platform.modeIndex];
uint32_t width = mode->hdisplay;
Expand Down Expand Up @@ -900,16 +891,8 @@ void SwapScreenBuffer(void)
}

// Copy the software rendered buffer to the dumb buffer with scaling if needed
if (bufferWidth == width && bufferHeight == height)
{
// Direct copy if sizes match
swCopyFramebuffer(0, 0, bufferWidth, bufferHeight, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);
}
else
{
// Scale the software buffer to match the display mode
swBlitFramebuffer(0, 0, width, height, 0, 0, bufferWidth, bufferHeight, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);
}
// NOTE: RLSW will make a simple copy if the dimensions match
swBlitFramebuffer(0, 0, width, height, 0, 0, width, height, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);

// Unmap the buffer
munmap(dumbBuffer, creq.size);
Expand Down
Loading