DRY SIMD fill color to image routines

This commit is contained in:
doyle 2020-07-04 21:55:58 +10:00
parent 77a949cfe7
commit 124abb7979

View File

@ -444,49 +444,16 @@ void RaylibSIMD_ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dst
Image RaylibSIMD_GenImageColor(int width, int height, Color color) Image RaylibSIMD_GenImageColor(int width, int height, Color color)
{ {
Color *pixels = RS_CAST(Color *)RL_CALLOC(width*height, sizeof(Color));
int num_pixels = width * height;
int simd_iterations = num_pixels / 4;
int remaining_iterations = num_pixels % 4;
__m128i *dest_4x = RS_CAST(__m128i *) pixels;
uint32_t color_u32 = RaylibSIMD__ColorToU32(color);
__m128i color_u32_4x = _mm_set1_epi32(color_u32);
for (int i = 0; i < simd_iterations; i++)
{
_mm_store_si128(dest_4x, color_u32_4x);
dest_4x++;
}
uint32_t *dest = RS_CAST(uint32_t *)dest_4x;
for (int i = 0; i < remaining_iterations; i++)
*dest++ = color_u32;
Image image = {0}; Image image = {0};
image.data = pixels; image.data = RS_CAST(Color *) RL_MALLOC(width * height * sizeof(Color));
image.width = width; image.width = width;
image.height = height; image.height = height;
image.format = UNCOMPRESSED_R8G8B8A8; image.format = UNCOMPRESSED_R8G8B8A8;
image.mipmaps = 1; image.mipmaps = 1;
RaylibSIMD_ImageDrawRectangleRec(&image, (Rectangle){0, 0, width, height}, color);
return image; return image;
} }
// Draw rectangle within an image
void RaylibSIMD_ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
{
// Security check to avoid program crash
if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0)) return;
Image imRec = RaylibSIMD_GenImageColor((int)rec.width, (int)rec.height, color);
RaylibSIMD_ImageDraw(dst, imRec, (Rectangle){0.f, 0.f, RS_CAST(float)rec.width, RS_CAST(float)rec.height}, rec, WHITE);
UnloadImage(imRec);
}
void RaylibSIMD_ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color)
{
RaylibSIMD_ImageDrawRectangleRec(dst, (Rectangle){RS_CAST(float)posX, RS_CAST(float)posY, RS_CAST(float)width, RS_CAST(float)height}, color);
}
RS_FILE_SCOPE int RaylibSIMD__FormatToBitsPerPixel(int format) RS_FILE_SCOPE int RaylibSIMD__FormatToBitsPerPixel(int format)
{ {
int result = 4; int result = 4;
@ -519,36 +486,56 @@ RS_FILE_SCOPE int RaylibSIMD__FormatToBitsPerPixel(int format)
return result; return result;
} }
void RaylibSIMD_ImageClearBackground(Image *dst, Color color) // Draw rectangle within an image
void RaylibSIMD_ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
{ {
// Security check to avoid program crash
if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0)) return;
if (dst->format == UNCOMPRESSED_R8G8B8A8) if (dst->format == UNCOMPRESSED_R8G8B8A8)
{ {
int bits_per_pixel = RaylibSIMD__FormatToBitsPerPixel(dst->format); int bits_per_pixel = RaylibSIMD__FormatToBitsPerPixel(dst->format);
int bytes_per_pixel = bits_per_pixel / 8; int bytes_per_pixel = bits_per_pixel / 8;
int total_pixels = dst->width * dst->height; int total_pixels = dst->width * dst->height;
int const SIMD_WIDTH = 4; int const SIMD_WIDTH = 4;
int simd_iterations = total_pixels / SIMD_WIDTH; int simd_iterations = dst->width / SIMD_WIDTH;
int remaining_iterations = total_pixels % SIMD_WIDTH; int remaining_iterations = dst->width % SIMD_WIDTH;
uint32_t color_u32 = RaylibSIMD__ColorToU32(color); uint32_t color_u32 = RaylibSIMD__ColorToU32(color);
__m128i color_u32_4x = _mm_set1_epi32(color_u32); __m128i color_u32_4x = _mm_set1_epi32(color_u32);
unsigned char *dest = dst->data; int stride = dst->width * bytes_per_pixel;
for (int iteration = 0; iteration < simd_iterations; iteration++) int row_offset = rec.x * bytes_per_pixel;
for (int y = 0; y < dst->height; y++)
{ {
_mm_storeu_si128((__m128i *)dest, color_u32_4x); unsigned char *dest_row = (unsigned char *)dst->data + (row_offset + (stride * y));
dest += (bytes_per_pixel * SIMD_WIDTH); unsigned char *dest = dest_row;
} for (int iteration = 0; iteration < simd_iterations; iteration++)
{
_mm_storeu_si128((__m128i *)dest, color_u32_4x);
dest += (bytes_per_pixel * SIMD_WIDTH);
}
for (int iteration = 0; iteration < remaining_iterations; iteration++) for (int iteration = 0; iteration < remaining_iterations; iteration++)
*dest++ = color_u32; *dest++ = color_u32;
}
} }
else else
{ {
// TODO(doyle): SIMD this path Image imRec = RaylibSIMD_GenImageColor((int)rec.width, (int)rec.height, color);
RaylibSIMD_ImageDrawRectangle(dst, 0, 0, dst->width, dst->height, color); RaylibSIMD_ImageDraw(dst, imRec, (Rectangle){0.f, 0.f, RS_CAST(float)rec.width, RS_CAST(float)rec.height}, rec, WHITE);
UnloadImage(imRec);
} }
} }
void RaylibSIMD_ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color)
{
RaylibSIMD_ImageDrawRectangleRec(dst, (Rectangle){RS_CAST(float)posX, RS_CAST(float)posY, RS_CAST(float)width, RS_CAST(float)height}, color);
}
void RaylibSIMD_ImageClearBackground(Image *dst, Color color)
{
RaylibSIMD_ImageDrawRectangleRec(dst, (Rectangle){0, 0, dst->width, dst->height}, color);
}
#endif // RAYLIB_SIMD_IMPLEMENTATION #endif // RAYLIB_SIMD_IMPLEMENTATION