mirror of
https://github.com/raysan5/raylib.git
synced 2025-12-06 06:13:10 +00:00
[rlsw] Fix axis aligned quad detection (#5314)
* fix `sw_quad_is_axis_aligned` * align fix * remove swGetColorBuffer and tweak DRM * review alignment
This commit is contained in:
parent
bf5c00f7e0
commit
cbff0fa22c
96
src/external/rlsw.h
vendored
96
src/external/rlsw.h
vendored
@ -531,7 +531,6 @@ SWAPI void swClose(void);
|
|||||||
SWAPI bool swResizeFramebuffer(int w, int h);
|
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 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 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 swEnable(SWstate state);
|
||||||
SWAPI void swDisable(SWstate state);
|
SWAPI void swDisable(SWstate state);
|
||||||
@ -616,12 +615,23 @@ SWAPI void swBindTexture(uint32_t id);
|
|||||||
#include <math.h> // Required for: floorf(), fabsf()
|
#include <math.h> // Required for: floorf(), fabsf()
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define ALIGNAS(x) __declspec(align(x))
|
#define SW_ALIGN(x) __declspec(align(x))
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
#define ALIGNAS(x) __attribute__((aligned(x)))
|
#define SW_ALIGN(x) __attribute__((aligned(x)))
|
||||||
#else
|
#else
|
||||||
#include <stdalign.h>
|
#define SW_ALIGN(x) // Do nothing if not available
|
||||||
#define ALIGNAS(x) alignas(x)
|
#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
|
#endif
|
||||||
|
|
||||||
#if defined(__FMA__) && defined(__AVX2__)
|
#if defined(__FMA__) && defined(__AVX2__)
|
||||||
@ -696,8 +706,15 @@ SWAPI void swBindTexture(uint32_t id);
|
|||||||
#define SW_DEG2RAD (SW_PI/180.0f)
|
#define SW_DEG2RAD (SW_PI/180.0f)
|
||||||
#define SW_RAD2DEG (180.0f/SW_PI)
|
#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_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)
|
#if (SW_COLOR_BUFFER_BITS == 8)
|
||||||
#define SW_COLOR_TYPE uint8_t
|
#define SW_COLOR_TYPE uint8_t
|
||||||
@ -827,10 +844,12 @@ typedef struct {
|
|||||||
} sw_texture_t;
|
} sw_texture_t;
|
||||||
|
|
||||||
// Pixel data type
|
// Pixel data type
|
||||||
// WARNING: ALIGNAS() macro requires a constant value (not operand)
|
typedef SW_ALIGN(SW_PIXEL_ALIGNMENT) struct {
|
||||||
typedef ALIGNAS(SW_COLOR_PIXEL_SIZE) struct {
|
|
||||||
SW_COLOR_TYPE color[SW_COLOR_PACK_COMP];
|
SW_COLOR_TYPE color[SW_COLOR_PACK_COMP];
|
||||||
SW_DEPTH_TYPE depth[SW_DEPTH_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;
|
} sw_pixel_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -2624,25 +2643,38 @@ static inline void sw_quad_clip_and_project(void)
|
|||||||
|
|
||||||
static inline bool sw_quad_is_axis_aligned(void)
|
static inline bool sw_quad_is_axis_aligned(void)
|
||||||
{
|
{
|
||||||
int horizontal = 0;
|
// Reject quads with perspective projection
|
||||||
int vertical = 0;
|
// 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++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;
|
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)
|
static inline void sw_quad_sort_cw(const sw_vertex_t* *output)
|
||||||
@ -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);
|
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 (wSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
|
||||||
if (hSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
|
if (hSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; }
|
||||||
|
|
||||||
@ -3674,6 +3701,13 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr
|
|||||||
xSrc = sw_clampi(xSrc, 0, wSrc);
|
xSrc = sw_clampi(xSrc, 0, wSrc);
|
||||||
ySrc = sw_clampi(ySrc, 0, hSrc);
|
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)
|
switch (pFormat)
|
||||||
{
|
{
|
||||||
case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
|
case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break;
|
||||||
@ -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)
|
void swEnable(SWstate state)
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
|
|||||||
@ -824,15 +824,6 @@ void SwapScreenBuffer(void)
|
|||||||
return;
|
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
|
// Retrieving the dimensions of the display mode used
|
||||||
drmModeModeInfo *mode = &platform.connector->modes[platform.modeIndex];
|
drmModeModeInfo *mode = &platform.connector->modes[platform.modeIndex];
|
||||||
uint32_t width = mode->hdisplay;
|
uint32_t width = mode->hdisplay;
|
||||||
@ -900,16 +891,8 @@ void SwapScreenBuffer(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy the software rendered buffer to the dumb buffer with scaling if needed
|
// Copy the software rendered buffer to the dumb buffer with scaling if needed
|
||||||
if (bufferWidth == width && bufferHeight == height)
|
// 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);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmap the buffer
|
// Unmap the buffer
|
||||||
munmap(dumbBuffer, creq.size);
|
munmap(dumbBuffer, creq.size);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user