Переглянути джерело

[rlsw] Fix axis aligned quad detection (#5314)

* fix `sw_quad_is_axis_aligned`

* align fix

* remove swGetColorBuffer and tweak DRM

* review alignment
pull/5317/head
Le Juez Victor 6 дні тому
committed by GitHub
джерело
коміт
cbff0fa22c
Не вдалося знайти GPG ключ що відповідає даному підпису Ідентифікатор GPG ключа: B5690EEEBB952194
2 змінених файлів з 63 додано та 54 видалено
  1. +61
    -35
      src/external/rlsw.h
  2. +2
    -19
      src/platforms/rcore_drm.c

+ 61
- 35
src/external/rlsw.h Переглянути файл

@ -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);
@ -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__)
@ -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
@ -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 {
@ -2624,25 +2643,38 @@ static inline void sw_quad_clip_and_project(void)
static inline bool sw_quad_is_axis_aligned(void)
{
kt">int horizontal = 0;
kt">int vertical = 0;
o">// Reject quads with perspective projection
o">// 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)
@ -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; }
@ -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;
@ -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)

+ 2
- 19
src/platforms/rcore_drm.c Переглянути файл

@ -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;
@ -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);

Завантаження…
Відмінити
Зберегти