74 lines
3.1 KiB
C
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;
|
||
|
}
|
||
|
}
|
||
|
}
|