Skip to content

Commit

Permalink
Clean canvas drawing functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sergystepanov committed Sep 23, 2023
1 parent 85cef0d commit 56d8c4a
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 137 deletions.
178 changes: 59 additions & 119 deletions pkg/worker/caged/libretro/image/canvas.c
Original file line number Diff line number Diff line change
@@ -1,142 +1,82 @@
#include "canvas.h"

__inline int rot_x(int t, int x, int y, int w, int h) {
__inline xy rotate(int t, int x, int y, int w, int h) {
xy p = {x, y};
switch (t) {
case 1:
return r90_x(x,y,w,h);
case A90:
p.x = r90_x(x,y,w,h);
p.y = r90_y(x,y,w,h);
break;
case 2:
return r180_x(x,y,w,h);
case A180:
p.x = r180_x(x,y,w,h);
p.y = r180_y(x,y,w,h);
break;
case 3:
return r270_x(x,y,w,h);
case A270:
p.x = r270_x(x,y,w,h);
p.y = r270_y(x,y,w,h);
break;
case 4:
return fy180_x(x,y,w,h);
case F180:
p.x = fy180_x(x,y,w,h);
p.y = fy180_y(x,y,w,h);
break;
}
return x;
return p;
}

__inline int rot_y(int t, int x, int y, int w, int h) {
switch (t) {
case 1:
return r90_y(x,y,w,h);
break;
case 2:
return r180_y(x,y,w,h);
break;
case 3:
return r270_y(x,y,w,h);
break;
case 4:
return fy180_y(x,y,w,h);
break;
}
return y;
}
__inline uint32_t _565(uint32_t x) {
return ((x >> 8 & 0xf8) | ((x >> 3 & 0xfc) << 8) | ((x << 3 & 0xfc) << 16)); // | 0xff000000
}

__inline uint32_t _8888rev(uint32_t px) {
return (((px >> 16) & 0xff) | (px & 0xff00) | ((px << 16) & 0xff0000)); // | 0xff000000)
}

void RGBA(int pix, uint32_t *__restrict dst, void *__restrict source, int y, int h, int w, int hh, int dw, int pad, int rot) {
int x;
xy rxy;

void RGBA(int pix, void *destination, void *source, int yy, int yn, int xw, int xh, int dw, int pad, int rot) {
switch (pix) {
case BIT_SHORT5551:
break;
//case BIT_SHORT5551:
// break;
case BIT_INT_8888REV:
if (rot == 0) {
i8888(destination, source, yy, yn, xw, pad);
uint32_t *src32 = source;
int pad32 = pad >> 2;
if (rot == NO_ROT) {
for (; y < h; ++y) {
for (x = 0; x < w; ++x) {
*dst++ = _8888rev(*src32++);
}
src32 += pad32;
}
} else {
i8888r(destination, source, yy, yn, xw, xh, dw, pad, rot);
for (; y < h; ++y) {
for (x = 0; x < w; ++x) {
rxy = rotate(rot, x, y, w, hh);
dst[rxy.x+rxy.y*w] = _8888rev(*src32++);
}
src32 += pad32;
}
}
break;
case BIT_SHORT565:
if (rot == 0) {
i565(destination, source, yy, yn, xw, pad);
uint16_t *src16 = source;
int pad16 = pad >> 1;
if (rot == NO_ROT) {
for (; y < h; ++y) {
for (x = 0; x < w; ++x) {
*dst++ = _565(*src16++);
}
src16 += pad16;
}
} else {
i565r(destination, source, yy, yn, xw, xh, dw, pad, rot);
for (; y < h; ++y) {
for (x = 0; x < w; ++x) {
rxy = rotate(rot, x, y, w, hh);
dst[rxy.x+rxy.y*dw] = _565(*src16++);
}
src16 += pad16;
}
}
break;
}
}

void i565(void *destination, void *source, int yy, int yn, int xw, int pad) {
uint8_t *src = source; // must be in bytes because of possible padding in bytes
uint32_t *dst = destination;

int y, x;
uint32_t px;

for (y = yy; y < yn; ++y) {
for (x = 0; x < xw; ++x) {
px = *(uint16_t *)src;
src += 2;
*dst++ = _565(px);
}
src += pad;
}
}

void i565r(void *destination, void *source, int yy, int yn, int xw, int xh, int dw, int pad, int rot) {
uint8_t *src = source;
uint32_t *dst = destination;

uint32_t px;

int x, y, dx, dy;

for (y = yy; y < yn; ++y) {
for (x = 0; x < xw; ++x) {
px = *(uint16_t *)src;
src += 2;

dx = rot_x(rot, x, y, xw, xh);
dy = rot_y(rot, x, y, xw, xh);

dst[dx+dy*dw] = _565(px);
}
src += pad;
}
}

void i8888r(void *destination, void *source, int yy, int yn, int xw, int xh, int dw, int pad, int rot) {
uint8_t *src = source;
uint32_t *dst = destination;

int y, x;
uint32_t px;

int dx, dy;

for (y = yy; y < yn; ++y) {
for (x = 0; x < xw; ++x) {
px = *(uint32_t *)src;

dx = rot_x(rot, x, y, xw, xh);
dy = rot_y(rot, x, y, xw, xh);

dst[dx+dy*dw] = _8888rev(px);
src += 4;
}
src += pad;
}
}

void i8888(void *destination, void *source, int yy, int yn, int xw, int pad) {
uint8_t *src = source; // must be in bytes because of possible padding in bytes
uint32_t *dst = destination;

int y, x;
uint32_t px;

for (y = yy; y < yn; ++y) {
for (x = 0; x < xw; ++x) {
px = *(uint32_t *)src;
src += 4;
*dst++ = _8888rev(px);
}
src += pad;
}
}

uint32_t px8888rev(uint32_t px) {
return _8888rev(px);
}
13 changes: 7 additions & 6 deletions pkg/worker/caged/libretro/image/canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,21 +138,22 @@ func (c *Canvas) Draw(encoding uint32, rot Rotation, w, h, packedW, bpp int, dat

func frame(encoding uint32, dst *Frame, data []byte, yy int, hn int, w int, h int, pwb int, bpp int, rot Rotation) {
sPtr := unsafe.Pointer(&data[yy*pwb])
dPtr := unsafe.Pointer(&dst.Pix[yy*dst.Stride])
// some cores can zero-right-pad rows to the packed width value
pad := pwb - w*bpp
if pad < 0 {
pad = 0
}
if rot != 0 {
dPtr = unsafe.Pointer(&dst.Pix[0])
ds := 0
if rot == 0 {
ds = yy * dst.Stride
}
dPtr := (*C.uint32_t)(unsafe.Pointer(&dst.Pix[ds]))
C.RGBA(C.int(encoding), dPtr, sPtr, C.int(yy), C.int(yy+hn), C.int(w), C.int(h), C.int(dst.Stride>>2), C.int(pad), C.int(rot))
}

func _8888rev(px uint32) uint32 { return uint32(C.px8888rev(C.uint32_t(px))) }
func _8888rev(px uint32) uint32 { return uint32(C._8888rev(C.uint32_t(px))) }

func rotate(t int, x int, y int, w int, h int) (int, int) {
return int(C.rot_x(C.int(t), C.int(x), C.int(y), C.int(w), C.int(h))),
int(C.rot_y(C.int(t), C.int(x), C.int(y), C.int(w), C.int(h)))
var rot C.xy = C.rotate(C.int(t), C.int(x), C.int(y), C.int(w), C.int(h))
return int(rot.x), int(rot.y)
}
25 changes: 13 additions & 12 deletions pkg/worker/caged/libretro/image/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
#define BIT_INT_8888REV 1
#define BIT_SHORT565 2

#define NO_ROT 0
#define A90 1
#define A180 2
#define A270 3
#define F180 4

// Rotate90 is 90° CCW or 270° CW.
#define r90_x(x, y, w, h) ( y )
#define r90_y(x, y, w, h) ( (w - 1) - x )
Expand All @@ -23,20 +29,15 @@
#define fy180_x(x, y, w, h) ( x )
#define fy180_y(x, y, w, h) ( (h - 1) - y )

int rot_x(int t, int x, int y, int w, int h);
int rot_y(int t, int x, int y, int w, int h);

#define _565(x) ((x >> 8 & 0xf8) | ((x >> 3 & 0xfc) << 8) | ((x << 3 & 0xfc) << 16)); // | 0xff000000
#define _8888rev(px) (((px >> 16) & 0xff) | (px & 0xff00) | ((px << 16) & 0xff0000)); // | 0xff000000)

typedef struct XY {
int x, y;
} xy;

void RGBA(int pix, void *destination, void *source, int yy, int yn, int xw, int xh, int dw, int pad, int rot);
xy rotate(int t, int x, int y, int w, int h);

void i565(void *destination, void *source, int yy, int yn, int xw, int pad);
void i8888(void *destination, void *source, int yy, int yn, int xw, int pad);
void i565r(void *destination, void *source, int yy, int yn, int xw, int xh, int dw, int pad, int rot);
void i8888r(void *destination, void *source, int yy, int yn, int xw, int xh, int dw, int pad, int rot);
void RGBA(int pix, uint32_t *dst, void *source, int y, int h, int w, int hh, int dw, int pad, int rot);

uint32_t px8888rev(uint32_t px);
uint32_t _565(uint32_t x);
uint32_t _8888rev(uint32_t px);

#endif

0 comments on commit 56d8c4a

Please sign in to comment.