graphics: render mouse using copying overlay, optimize copying
This commit is contained in:
parent
986b135403
commit
a0c2b8d8fd
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "internal_helpers.h"
|
||||||
#include "unifont.h"
|
#include "unifont.h"
|
||||||
#include "../runtime/stdio.h"
|
#include "../runtime/stdio.h"
|
||||||
#include "../util/minmax.h"
|
#include "../util/minmax.h"
|
||||||
@ -36,8 +37,11 @@ void * graphics_Framebuffer;
|
|||||||
uint64_t graphics_FramebufferSize;
|
uint64_t graphics_FramebufferSize;
|
||||||
uint32_t graphics_Doublebuffer[2048 * 1024];
|
uint32_t graphics_Doublebuffer[2048 * 1024];
|
||||||
|
|
||||||
|
#define MOUSE_OVERLAY_SIZE 32
|
||||||
xcursor_ChunkHeader_Image *graphics_Cursor;
|
xcursor_ChunkHeader_Image *graphics_Cursor;
|
||||||
int graphics_MouseCursorX, graphics_MouseCursorY;
|
int graphics_MouseCursorX, graphics_MouseCursorY;
|
||||||
|
static int __lastMouseX, __lastMouseY; // Last of mouse **IMAGE** position
|
||||||
|
static uint32_t __mouseOverlay[MOUSE_OVERLAY_SIZE * MOUSE_OVERLAY_SIZE];
|
||||||
|
|
||||||
|
|
||||||
void graphics_Init() {
|
void graphics_Init() {
|
||||||
@ -160,36 +164,35 @@ void graphics_ClearBuffer(const HelosGraphics_Color *color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void graphics_SwapBuffer() {
|
static void __graphics__UpdateMouse() {
|
||||||
memcpy(graphics_DeviceFramebuffer, graphics_Framebuffer, graphics_FramebufferSize);
|
if (!graphics_Cursor)
|
||||||
|
return;
|
||||||
|
|
||||||
if (graphics_Cursor) {
|
int imgX = graphics_MouseCursorX - graphics_Cursor->xhot + 1;
|
||||||
// TODO Optimize mouse cursor overlay render
|
int imgY = graphics_MouseCursorY - graphics_Cursor->yhot + 1;
|
||||||
/*if (graphics_SystemVideoMode.PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
|
if (imgX != __lastMouseX || imgY != __lastMouseY) { // moved
|
||||||
for (int i = 0; i < graphics_Cursor->height; i++) {
|
__graphics_CopyBuffer32(
|
||||||
if (graphics_MouseCursorY + i >= graphics_SystemVideoMode.Height)
|
__mouseOverlay, 0, 0, MOUSE_OVERLAY_SIZE, MOUSE_OVERLAY_SIZE,
|
||||||
break;
|
graphics_Framebuffer, __lastMouseX, __lastMouseY, graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height,
|
||||||
memcpy(
|
graphics_Cursor->width, graphics_Cursor->height);
|
||||||
graphics_DeviceFramebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * graphics_CursorY + 4 * graphics_CursorX,
|
__graphics_CopyBuffer32(
|
||||||
&graphics_Cursor->pixels[i * graphics_Cursor->width],
|
graphics_Framebuffer, imgX, imgY, graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height,
|
||||||
min(graphics_Cursor->width, graphics_SystemVideoMode.Width - graphics_MouseCursorX) * 4);
|
__mouseOverlay, 0, 0, MOUSE_OVERLAY_SIZE, MOUSE_OVERLAY_SIZE,
|
||||||
}
|
graphics_Cursor->width, graphics_Cursor->height);
|
||||||
} else {*/
|
__graphics_RenderBuffer32(
|
||||||
int imgX = graphics_MouseCursorX - graphics_Cursor->xhot + 1;
|
graphics_Cursor->pixels, 0, 0, graphics_Cursor->width, graphics_Cursor->height,
|
||||||
int imgY = graphics_MouseCursorY - graphics_Cursor->yhot + 1;
|
graphics_Framebuffer, imgX, imgY, graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height,
|
||||||
for (int y = intmax(imgY, 0); y < intmin(imgY + graphics_Cursor->height, graphics_SystemVideoMode.Height); y++) {
|
graphics_Cursor->width, graphics_Cursor->height);
|
||||||
for (int x = intmax(imgX, 0); x < intmin(imgX + graphics_Cursor->width, graphics_SystemVideoMode.Width); x++) {
|
__lastMouseX = imgX;
|
||||||
//graphics_SetPixel_RGB(x + graphics_MouseCursorX, y + graphics_MouseCursorY, &graphics_Cursor->pixels[y * graphics_Cursor->width + x]);
|
__lastMouseY = imgY;
|
||||||
HelosGraphics_Color *pixel = &graphics_Cursor->pixels[(y - imgY) * graphics_Cursor->width + (x - imgX)];
|
|
||||||
if (pixel->A <= 0x7f)
|
|
||||||
continue;
|
|
||||||
*((uint32_t *)(graphics_DeviceFramebuffer + graphics_SystemVideoMode.PixelsPerLine * 4 * y + 4 * x)) = (*((uint32_t *)pixel)) & 0x00ffffffu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void graphics_SwapBuffer() {
|
||||||
|
__graphics__UpdateMouse();
|
||||||
|
memcpy(graphics_DeviceFramebuffer, graphics_Framebuffer, graphics_FramebufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
void graphics_FillPixel(int startX, int startY, int endX, int endY, const HelosGraphics_Color *color) {
|
void graphics_FillPixel(int startX, int startY, int endX, int endY, const HelosGraphics_Color *color) {
|
||||||
// TODO Optimize this! This is too sloooow
|
// TODO Optimize this! This is too sloooow
|
||||||
if (graphics_SystemVideoMode.PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
|
if (graphics_SystemVideoMode.PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
|
||||||
@ -221,6 +224,7 @@ void graphics_Scroll(int scrollY) {
|
|||||||
0,
|
0,
|
||||||
sizeof(uint32_t) * graphics_SystemVideoMode.PixelsPerLine * (scrollY));*/
|
sizeof(uint32_t) * graphics_SystemVideoMode.PixelsPerLine * (scrollY));*/
|
||||||
graphics_FillPixel(0, graphics_SystemVideoMode.Height - scrollY, graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height, &HelosGraphics_Color_Black);
|
graphics_FillPixel(0, graphics_SystemVideoMode.Height - scrollY, graphics_SystemVideoMode.Width, graphics_SystemVideoMode.Height, &HelosGraphics_Color_Black);
|
||||||
|
__lastMouseY -= scrollY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void graphics_ElementSize(int sizeX, int sizeY) {
|
void graphics_ElementSize(int sizeX, int sizeY) {
|
||||||
|
73
graphics/internal_helpers.h
Normal file
73
graphics/internal_helpers.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,3 +8,27 @@ static inline int intmin(int x, int y) {
|
|||||||
static inline int intmax(int x, int y) {
|
static inline int intmax(int x, int y) {
|
||||||
return x > y ? x : y;
|
return x > y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int intmin3(int x, int y, int z) {
|
||||||
|
if (x < y)
|
||||||
|
if (x < z)
|
||||||
|
return x;
|
||||||
|
else
|
||||||
|
return z;
|
||||||
|
else if (y < z)
|
||||||
|
return y;
|
||||||
|
else
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int intmax3(int x, int y, int z) {
|
||||||
|
if (x > y)
|
||||||
|
if (x > z)
|
||||||
|
return x;
|
||||||
|
else
|
||||||
|
return z;
|
||||||
|
else if (y > z)
|
||||||
|
return y;
|
||||||
|
else
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user