Merge branch 'raysan5:master' into patch-1
This commit is contained in:
commit
28efddf6d4
81
src/external/rlsw.h
vendored
81
src/external/rlsw.h
vendored
|
|
@ -5385,6 +5385,16 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
|||
int xEnd = (int)end->position[0];
|
||||
if (xStart == xEnd) return;
|
||||
|
||||
// Intercept the span bounds to ensure to not write before the framebuffer
|
||||
int xLoopStart = (xStart >= 0)? xStart : 0;
|
||||
int xLoopEnd = (xEnd <= RLSW.colorBuffer->width)? xEnd : RLSW.colorBuffer->width;
|
||||
if (xLoopStart >= xLoopEnd) return; // Nothing to draw
|
||||
|
||||
// Get the current row and skip if outside the framebuffer
|
||||
// Maybe this check is better suited elsewhere?
|
||||
int y = (int)start->position[1];
|
||||
if (y < 0 || y >= RLSW.colorBuffer->height) return;
|
||||
|
||||
// Compute the inverse horizontal distance along the X axis
|
||||
float dxRcp = sw_rcp(end->position[0] - start->position[0]);
|
||||
|
||||
|
|
@ -5405,27 +5415,29 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
|||
#endif
|
||||
|
||||
// Compute the subpixel distance to traverse before the first pixel
|
||||
// Also step further into them to move away from the colorbuffer edge
|
||||
float xSubstep = 1.0f - sw_fract(start->position[0]);
|
||||
float dxStart = (float)(xLoopStart - xStart);
|
||||
float xOffset = xSubstep + dxStart;
|
||||
|
||||
// Initializing the interpolation starting values
|
||||
float w = start->position[3] + dWdx*xSubstep;
|
||||
float w = start->position[3] + dWdx*xOffset;
|
||||
float color[4] = {
|
||||
start->color[0] + dCdx[0]*xSubstep,
|
||||
start->color[1] + dCdx[1]*xSubstep,
|
||||
start->color[2] + dCdx[2]*xSubstep,
|
||||
start->color[3] + dCdx[3]*xSubstep
|
||||
start->color[0] + dCdx[0]*xOffset,
|
||||
start->color[1] + dCdx[1]*xOffset,
|
||||
start->color[2] + dCdx[2]*xOffset,
|
||||
start->color[3] + dCdx[3]*xOffset
|
||||
};
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
float z = start->position[2] + dZdx*xSubstep;
|
||||
float z = start->position[2] + dZdx*xOffset;
|
||||
#endif
|
||||
#ifdef SW_ENABLE_TEXTURE
|
||||
float u = start->texcoord[0] + dUdx*xSubstep;
|
||||
float v = start->texcoord[1] + dVdx*xSubstep;
|
||||
float u = start->texcoord[0] + dUdx*xOffset;
|
||||
float v = start->texcoord[1] + dVdx*xOffset;
|
||||
#endif
|
||||
|
||||
// Pre-calculate the starting pointers for the framebuffer row
|
||||
int y = (int)start->position[1];
|
||||
int baseOffset = y*RLSW.colorBuffer->width + xStart;
|
||||
int baseOffset = y*RLSW.colorBuffer->width + xLoopStart;
|
||||
uint8_t *cPtr = (uint8_t *)(RLSW.colorBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
uint8_t *dPtr = (uint8_t *)(RLSW.depthBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
|
||||
|
|
@ -5433,12 +5445,12 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
|||
|
||||
#define SW_AFFINE_BLOCK 16
|
||||
|
||||
int x = xStart;
|
||||
while (x < xEnd)
|
||||
int x = xLoopStart;
|
||||
while (x < xLoopEnd)
|
||||
{
|
||||
// Clamp last block to remaining pixels
|
||||
int blockEnd = x + SW_AFFINE_BLOCK;
|
||||
if (blockEnd > xEnd) blockEnd = xEnd;
|
||||
if (blockEnd > xLoopEnd) blockEnd = xLoopEnd;
|
||||
float blockLenF = (float)(blockEnd - x);
|
||||
float blockLenRcp = sw_rcp(blockLenF);
|
||||
|
||||
|
|
@ -5673,6 +5685,14 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
|||
int xMax = (int)br->position[0];
|
||||
int yMax = (int)br->position[1];
|
||||
|
||||
// Exit early if no pixels to draw. Use these later for loop boundaries
|
||||
int yLoopMin = (yMin >= 0)? yMin : 0;
|
||||
int xLoopMin = (xMin >= 0)? xMin : 0;
|
||||
int yLoopMax = (yMax <= RLSW.colorBuffer->height)? yMax : RLSW.colorBuffer->height;
|
||||
int xLoopMax = (xMax <= RLSW.colorBuffer->width)? xMax : RLSW.colorBuffer->width;
|
||||
|
||||
if (yLoopMin >= yLoopMax || xLoopMin >= xLoopMax) return;
|
||||
|
||||
float w = (float)(xMax - xMin);
|
||||
float h = (float)(yMax - yMin);
|
||||
if ((w <= 0) || (h <= 0)) return;
|
||||
|
|
@ -5726,21 +5746,44 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
|||
uint8_t *dPixels = RLSW.depthBuffer->pixels;
|
||||
#endif
|
||||
|
||||
for (int y = yMin; y < yMax; y++)
|
||||
// Calculate the distance the in-bounds boundary is from the quad's edges, only on the left and top
|
||||
float dxMin = (float)(xLoopMin - xMin);
|
||||
float dyMin = (float)(yLoopMin - yMin);
|
||||
|
||||
// Correct our start by how far it's clipped outside the framebuffer
|
||||
cRow[0] += dCdx[0]*dxMin + dCdy[0]*dyMin;
|
||||
cRow[1] += dCdx[1]*dxMin + dCdy[1]*dyMin;
|
||||
cRow[2] += dCdx[2]*dxMin + dCdy[2]*dyMin;
|
||||
cRow[3] += dCdx[3]*dxMin + dCdy[3]*dyMin;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
zRow += dZdy*dyMin + dZdx*dxMin;
|
||||
#endif
|
||||
#ifdef SW_ENABLE_TEXTURE
|
||||
uRow += dUdy*dyMin + dUdx*dxMin;
|
||||
vRow += dVdy*dyMin + dVdx*dxMin;
|
||||
#endif
|
||||
|
||||
for (int y = yLoopMin; y < yLoopMax; y++)
|
||||
{
|
||||
int baseOffset = y*stride + xMin;
|
||||
int baseOffset = y*stride + xLoopMin;
|
||||
uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
|
||||
// Copy the cursors without destroying the offset maths
|
||||
float z = zRow;
|
||||
#endif
|
||||
#ifdef SW_ENABLE_TEXTURE
|
||||
float u = uRow;
|
||||
float v = vRow;
|
||||
#endif
|
||||
float color[4] = { cRow[0], cRow[1], cRow[2], cRow[3] };
|
||||
float color[4] = {
|
||||
cRow[0],
|
||||
cRow[1],
|
||||
cRow[2],
|
||||
cRow[3]
|
||||
};
|
||||
|
||||
for (int x = xMin; x < xMax; x++)
|
||||
for (int x = xLoopMin; x < xLoopMax; x++)
|
||||
{
|
||||
float srcColor[4] = { color[0], color[1], color[2], color[3] };
|
||||
|
||||
|
|
@ -5779,6 +5822,7 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
|||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
discard:
|
||||
#endif
|
||||
// Move one pixel over without touching the original "start offset"
|
||||
color[0] += dCdx[0];
|
||||
color[1] += dCdx[1];
|
||||
color[2] += dCdx[2];
|
||||
|
|
@ -5801,6 +5845,9 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
|||
cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
|
||||
}
|
||||
|
||||
// The for loop is clamped to the right side of the screen
|
||||
// However, these cursor start vars are still on the left
|
||||
// That's fine, advancing to the next row
|
||||
cRow[0] += dCdy[0];
|
||||
cRow[1] += dCdy[1];
|
||||
cRow[2] += dCdy[2];
|
||||
|
|
|
|||
10
src/external/rprand.h
vendored
10
src/external/rprand.h
vendored
|
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* rprand v1.0 - A simple and easy-to-use pseudo-random numbers generator (PRNG)
|
||||
* rprand v1.1 - A simple and easy-to-use pseudo-random numbers generator (PRNG)
|
||||
*
|
||||
* FEATURES:
|
||||
* - Pseudo-random values generation, 32 bits: [0..4294967295]
|
||||
|
|
@ -118,6 +118,7 @@ extern "C" { // Prevents name mangling of functions
|
|||
//----------------------------------------------------------------------------------
|
||||
RPRANDAPI void rprand_set_seed(unsigned long long seed); // Set rprand_state for Xoshiro128**, seed is 64bit
|
||||
RPRANDAPI int rprand_get_value(int min, int max); // Get random value within a range, min and max included
|
||||
RPRANDAPI int rprand_get_value_raw(void); // Get random value, Xoshiro128** generator (uses global rprand_state)
|
||||
|
||||
RPRANDAPI int *rprand_load_sequence(unsigned int count, int min, int max); // Load pseudo-random numbers sequence with no duplicates
|
||||
RPRANDAPI void rprand_unload_sequence(int *sequence); // Unload pseudo-random numbers sequence
|
||||
|
|
@ -186,6 +187,13 @@ int rprand_get_value(int min, int max)
|
|||
return value;
|
||||
}
|
||||
|
||||
int rprand_get_value_raw(void)
|
||||
{
|
||||
int value = rprand_xoshiro();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Load pseudo-random numbers sequence with no duplicates, min and max included
|
||||
int *rprand_load_sequence(unsigned int count, int min, int max)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1042,11 +1042,6 @@ const char *GetClipboardText(void)
|
|||
return glfwGetClipboardString(platform.handle);
|
||||
}
|
||||
|
||||
#if SUPPORT_CLIPBOARD_IMAGE && defined(__linux__) && defined(_GLFW_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#endif
|
||||
|
||||
// Get clipboard image
|
||||
Image GetClipboardImage(void)
|
||||
{
|
||||
|
|
@ -1066,32 +1061,30 @@ Image GetClipboardImage(void)
|
|||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)bmpData, (int)dataSize);
|
||||
|
||||
#elif defined(__linux__) && defined(_GLFW_X11)
|
||||
|
||||
// REF: https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
if (!dpy) return image;
|
||||
|
||||
Window root = DefaultRootWindow(dpy);
|
||||
Window win = XCreateSimpleWindow(
|
||||
dpy, // The connection to the X Server
|
||||
root, // The 'Parent' window (usually the desktop/root)
|
||||
0, 0, // X and Y position on the screen
|
||||
1, 1, // Width and Height (1x1 pixel)
|
||||
0, // Border width
|
||||
0, // Border color
|
||||
0 // Background color
|
||||
);
|
||||
static Atom clipboard = 0;
|
||||
static Atom targetType = 0;
|
||||
static Atom property = 0;
|
||||
|
||||
Atom clipboard = XInternAtom(dpy, "CLIPBOARD", False);
|
||||
Atom targetType = XInternAtom(dpy, "image/png", False); // Ask for PNG
|
||||
Atom property = XInternAtom(dpy, "RAYLIB_CLIPBOARD_MANAGER", False);
|
||||
Display *display = glfwGetX11Display();
|
||||
XID window = glfwGetX11Window(platform.handle);
|
||||
|
||||
// Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER"
|
||||
XConvertSelection(dpy, clipboard, targetType, property, win, CurrentTime);
|
||||
// Lazy-load X11 atoms
|
||||
if(clipboard == 0)
|
||||
{
|
||||
clipboard = XInternAtom(display, "CLIPBOARD", False);
|
||||
targetType = XInternAtom(display, "image/png", False);
|
||||
property = XInternAtom(display, "RAYLIB_CLIPBOARD_MANAGER", False);
|
||||
}
|
||||
|
||||
XConvertSelection(display, clipboard, targetType, property, window, CurrentTime);
|
||||
XSync(display, 0);
|
||||
|
||||
// Wait for the SelectionNotify event
|
||||
XEvent ev = { 0 };
|
||||
XNextEvent(dpy, &ev);
|
||||
|
||||
// Keep calling until we get SelectionNotify
|
||||
while (XCheckTypedEvent(display, SelectionNotify, &ev) == False);
|
||||
|
||||
Atom actualType = { 0 };
|
||||
int actualFormat = 0;
|
||||
|
|
@ -1099,9 +1092,8 @@ Image GetClipboardImage(void)
|
|||
unsigned long bytesAfter = 0;
|
||||
unsigned char *data = NULL;
|
||||
|
||||
// Read the data from our ghost window's property
|
||||
XGetWindowProperty(dpy, win, property, 0, ~0L, False, AnyPropertyType,
|
||||
&actualType, &actualFormat, &nitems, &bytesAfter, &data);
|
||||
XGetWindowProperty(display, window, property, 0, ~0L, False, AnyPropertyType,
|
||||
&actualType, &actualFormat, &nitems, &bytesAfter, &data);
|
||||
|
||||
if (data != NULL)
|
||||
{
|
||||
|
|
@ -1109,8 +1101,6 @@ Image GetClipboardImage(void)
|
|||
XFree(data);
|
||||
}
|
||||
|
||||
XDestroyWindow(dpy, win);
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
|
||||
#endif // _WIN32
|
||||
|
|
|
|||
|
|
@ -960,7 +960,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
|||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
|
||||
segments = (int)(ceilf(2*PI/th)/4.0f);
|
||||
segments = (int)(ceilf(2*PI/th)/2.0f);
|
||||
if (segments <= 0) segments = 4;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user