helos1/graphics/internal_helpers.h

74 lines
3.1 KiB
C

#pragma once
#include "../util/minmax.h"
#include "color.h"
#include "stdint.h"
#include "string.h"
static inline void __graphics_CopyBuffer32(
void *from, // Source image of the copy
int fromOffsetX, // OffsetX of the region to copy from
int fromOffsetY, // OffsetY of the region to copy from
int fromSizeX, // SizeX of the entire source image
int fromSizeY, // SizeY of the entire source image
void *to, // Destination image of the copy
int toOffsetX, // OffsetX of the target region
int toOffsetY, // OffsetY of the target region
int toSizeX, // SizeX of the entire destination image
int toSizeY, // SizeY of the entire destination image
int countX, // Size of the copying region
int countY) {
int beginX = intmax3(0, -fromOffsetX, -toOffsetX), beginY = intmax3(0, -fromOffsetY, -toOffsetY);
int endX = intmin3(countX, fromSizeX - fromOffsetX, toSizeX - toOffsetX),
endY = intmin3(countY, fromSizeY - fromOffsetY, toSizeY - toOffsetY);
#define PIXEL_BYTES ((intptr_t)4)
for (int i = beginY; i < endY; i++)
memcpy(
((intptr_t)toOffsetX + beginX + (intptr_t)toSizeX * (toOffsetY + i)) * PIXEL_BYTES + (uint8_t *)to,
((intptr_t)fromOffsetX + beginX + (intptr_t)fromSizeX * (fromOffsetY + i)) * PIXEL_BYTES + (uint8_t *)from,
(endX - beginX) * PIXEL_BYTES);
#undef PIXEL_BYTES
}
// Blends ARGB Premultiplied Alpha image onto (opaque) buffer
// See: https://apoorvaj.io/alpha-compositing-opengl-blending-and-premultiplied-alpha/
static inline void __graphics_RenderBuffer32(
void *from, // Source image of the render
int fromOffsetX, // OffsetX of the region to render from
int fromOffsetY, // OffsetY of the region to render from
int fromSizeX, // SizeX of the entire source image
int fromSizeY, // SizeY of the entire source image
void *to, // Destination image of the render
int toOffsetX, // OffsetX of the target region
int toOffsetY, // OffsetY of the target region
int toSizeX, // SizeX of the entire destination image
int toSizeY, // SizeY of the entire destination image
int countX, // Size of the render region
int countY) {
int beginX = intmax3(0, -fromOffsetX, -toOffsetX), beginY = intmax3(0, -fromOffsetY, -toOffsetY);
int endX = intmin3(countX, fromSizeX - fromOffsetX, toSizeX - toOffsetX),
endY = intmin3(countY, fromSizeY - fromOffsetY, toSizeY - toOffsetY);
for (int x = beginX; x < endX; x++)
for (int y = beginY; y < endY; y++) {
HelosGraphics_Color
*src = ((intptr_t)fromOffsetX + x + (intptr_t)fromSizeX * (fromOffsetY + y)) + (HelosGraphics_Color *)from,
*dest = ((intptr_t)toOffsetX + x + (intptr_t)toSizeX * (toOffsetY + y)) + (HelosGraphics_Color *)to;
if (src->A == 0)
continue;
else if (src->A == 0xff)
*(uint32_t *)dest = *(uint32_t *)src & 0x00ffffffu;
else { // blend
HelosGraphics_Color color = {
.B = (uint8_t)(src->B + ((int)dest->B) * (0xff - src->A) / 0xff),
.G = (uint8_t)(src->G + ((int)dest->G) * (0xff - src->A) / 0xff),
.R = (uint8_t)(src->R + ((int)dest->R) * (0xff - src->A) / 0xff),
.A = 0};
*dest = color;
}
}
}