mirror of
https://github.com/libretro/xmil-libretro.git
synced 2024-11-23 16:19:43 +00:00
38380d7b3f
refs #94 svn merge -r 148:149 https://amethyst.yui.ne.jp/svn-dev/x1/xmil/branches/yui/WORK_01
654 lines
13 KiB
C
654 lines
13 KiB
C
/**
|
|
* @file vramhdl.c
|
|
* @brief Implementation of the vram
|
|
*/
|
|
|
|
#include "compiler.h"
|
|
#include "vramhdl.h"
|
|
#include "common/resize.h"
|
|
|
|
VRAMHDL vram_create(int width, int height, BOOL alpha, int bpp) {
|
|
|
|
int size;
|
|
int allocsize;
|
|
int xalign;
|
|
int alphasize;
|
|
VRAMHDL ret;
|
|
|
|
#if defined(SCREEN_BPP)
|
|
if (bpp == DEFAULT_BPP) {
|
|
bpp = SCREEN_BPP;
|
|
}
|
|
#endif
|
|
size = width * height;
|
|
xalign = (bpp + 7) >> 3;
|
|
if ((width <= 0) || (size <= 0) || (size > 0x1000000) ||
|
|
(xalign <= 0) || (xalign > 4)) {
|
|
return(NULL);
|
|
}
|
|
allocsize = sizeof(_VRAMHDL);
|
|
allocsize += size * xalign;
|
|
alphasize = 0;
|
|
if (alpha) {
|
|
alphasize = (size + 7) & (~7); // boundary!!
|
|
allocsize += alphasize;
|
|
}
|
|
#ifdef MEMTRACE
|
|
{
|
|
char buf[128];
|
|
sprintf(buf, "VRAM %dx%d (%d)", width, height, bpp);
|
|
ret = (VRAMHDL)_MALLOC(allocsize, buf);
|
|
}
|
|
#else
|
|
ret = (VRAMHDL)_MALLOC(allocsize, "VRAM");
|
|
#endif
|
|
if (ret) {
|
|
ZeroMemory(ret, allocsize);
|
|
ret->width = width;
|
|
ret->height = height;
|
|
ret->xalign = xalign;
|
|
ret->yalign = xalign * width;
|
|
ret->bpp = bpp;
|
|
ret->scrnsize = size;
|
|
if (alpha) {
|
|
ret->alpha = (UINT8 *)(ret + 1);
|
|
ret->ptr = ret->alpha + alphasize;
|
|
}
|
|
else {
|
|
ret->ptr = (UINT8 *)(ret + 1);
|
|
}
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
void vram_destroy(VRAMHDL hdl) {
|
|
|
|
if (hdl) {
|
|
if ((hdl->alpha) && (hdl->alpha != (UINT8 *)(hdl + 1))) {
|
|
_MFREE(hdl->alpha);
|
|
}
|
|
_MFREE(hdl);
|
|
}
|
|
}
|
|
|
|
BRESULT vram_allocalpha(VRAMHDL hdl) {
|
|
|
|
if (hdl == NULL) {
|
|
return(FAILURE);
|
|
}
|
|
if (hdl->alpha == NULL) {
|
|
hdl->alpha = (UINT8 *)_MALLOC(hdl->scrnsize, "alpha plane");
|
|
if (hdl->alpha == NULL) {
|
|
return(FAILURE);
|
|
}
|
|
ZeroMemory(hdl->alpha, hdl->scrnsize);
|
|
}
|
|
return(SUCCESS);
|
|
}
|
|
|
|
void vram_zerofill(VRAMHDL hdl, const RECT_T *rect) {
|
|
|
|
int ptr;
|
|
int width;
|
|
int height;
|
|
int pos;
|
|
int remain;
|
|
UINT8 *p;
|
|
|
|
if (hdl) {
|
|
if (rect == NULL) {
|
|
ZeroMemory(hdl->ptr, hdl->scrnsize * hdl->xalign);
|
|
if (hdl->alpha) {
|
|
ZeroMemory(hdl->alpha, hdl->scrnsize);
|
|
}
|
|
}
|
|
else {
|
|
pos = max(rect->left, 0);
|
|
ptr = pos;
|
|
width = min(rect->right, hdl->width) - pos;
|
|
pos = max(rect->top, 0);
|
|
ptr += pos * hdl->width;
|
|
height = min(rect->bottom, hdl->height) - pos;
|
|
if ((width > 0) && (height > 0)) {
|
|
p = hdl->ptr;
|
|
p += ptr * hdl->xalign;
|
|
remain = height;
|
|
do {
|
|
ZeroMemory(p, width * hdl->xalign);
|
|
p += hdl->yalign;
|
|
} while(--remain);
|
|
|
|
if (hdl->alpha) {
|
|
p = hdl->alpha + ptr;
|
|
remain = height;
|
|
do {
|
|
ZeroMemory(p, width);
|
|
p += hdl->width;
|
|
} while(--remain);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vram_fill(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha) {
|
|
|
|
int ptr;
|
|
int width;
|
|
int height;
|
|
int pos;
|
|
int remain;
|
|
UINT8 *p;
|
|
#ifdef SUPPORT_16BPP
|
|
UINT c16;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
UINT8 c24[3];
|
|
#endif
|
|
|
|
if (hdl == NULL) {
|
|
return;
|
|
}
|
|
if (rect == NULL) {
|
|
p = hdl->ptr;
|
|
remain = hdl->scrnsize;
|
|
switch(hdl->bpp) {
|
|
case 8:
|
|
do {
|
|
*p++ = (UINT8)color;
|
|
} while(--remain);
|
|
break;
|
|
#ifdef SUPPORT_16BPP
|
|
case 16:
|
|
c16 = MAKE16PAL(color);
|
|
do {
|
|
*(UINT16 *)p = (UINT16)c16;
|
|
p += 2;
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
case 24:
|
|
c24[0] = (UINT8)color;
|
|
c24[1] = (UINT8)(color >> 8);
|
|
c24[2] = (UINT8)(color >> 16);
|
|
do {
|
|
p[0] = c24[0];
|
|
p[1] = c24[1];
|
|
p[2] = c24[2];
|
|
p += 3;
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
default:
|
|
TRACEOUT(("vram_fill: unsupport %dbpp", hdl->bpp));
|
|
break;
|
|
}
|
|
if (hdl->alpha) {
|
|
FillMemory(hdl->alpha, hdl->scrnsize, alpha);
|
|
}
|
|
}
|
|
else {
|
|
pos = max(rect->left, 0);
|
|
ptr = pos;
|
|
width = min(rect->right, hdl->width) - pos;
|
|
pos = max(rect->top, 0);
|
|
ptr += pos * hdl->width;
|
|
height = min(rect->bottom, hdl->height) - pos;
|
|
if ((width > 0) && (height > 0)) {
|
|
p = hdl->ptr;
|
|
p += ptr * hdl->xalign;
|
|
switch(hdl->bpp) {
|
|
case 8:
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
*p++ = (UINT8)color;
|
|
} while(--r);
|
|
p += hdl->yalign - width;
|
|
} while(--remain);
|
|
break;
|
|
#ifdef SUPPORT_16BPP
|
|
case 16:
|
|
c16 = MAKE16PAL(color);
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
*(UINT16 *)p = (UINT16)c16;
|
|
p += 2;
|
|
} while(--r);
|
|
p += hdl->yalign - (width * 2);
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
case 24:
|
|
c24[0] = (UINT8)color;
|
|
c24[1] = (UINT8)(color >> 8);
|
|
c24[2] = (UINT8)(color >> 16);
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
p[0] = c24[0];
|
|
p[1] = c24[1];
|
|
p[2] = c24[2];
|
|
p += 3;
|
|
} while(--r);
|
|
p += hdl->yalign - (width * 3);
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
default:
|
|
TRACEOUT(("vram_fill: unsupport %dbpp", hdl->bpp));
|
|
break;
|
|
}
|
|
if (hdl->alpha) {
|
|
p = hdl->alpha + ptr;
|
|
remain = height;
|
|
do {
|
|
FillMemory(p, width, alpha);
|
|
p += hdl->width;
|
|
} while(--remain);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vram_filldat(VRAMHDL hdl, const RECT_T *rect, UINT32 color) {
|
|
|
|
int ptr;
|
|
int width;
|
|
int height;
|
|
int pos;
|
|
int remain;
|
|
UINT8 *p;
|
|
#ifdef SUPPORT_16BPP
|
|
UINT c16;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
UINT8 c24[3];
|
|
#endif
|
|
|
|
if (hdl == NULL) {
|
|
return;
|
|
}
|
|
if (rect == NULL) {
|
|
p = hdl->ptr;
|
|
remain = hdl->scrnsize;
|
|
switch(hdl->bpp) {
|
|
case 8:
|
|
do {
|
|
*p++ = (UINT8)color;
|
|
} while(--remain);
|
|
break;
|
|
#ifdef SUPPORT_16BPP
|
|
case 16:
|
|
c16 = MAKE16PAL(color);
|
|
do {
|
|
*(UINT16 *)p = (UINT16)c16;
|
|
p += 2;
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
case 24:
|
|
c24[0] = (UINT8)color;
|
|
c24[1] = (UINT8)(color >> 8);
|
|
c24[2] = (UINT8)(color >> 16);
|
|
do {
|
|
p[0] = c24[0];
|
|
p[1] = c24[1];
|
|
p[2] = c24[2];
|
|
p += 3;
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
default:
|
|
TRACEOUT(("vram_filldat: unsupport %dbpp", hdl->bpp));
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
pos = max(rect->left, 0);
|
|
ptr = pos;
|
|
width = min(rect->right, hdl->width) - pos;
|
|
pos = max(rect->top, 0);
|
|
ptr += pos * hdl->width;
|
|
height = min(rect->bottom, hdl->height) - pos;
|
|
if ((width > 0) && (height > 0)) {
|
|
p = hdl->ptr;
|
|
p += ptr * hdl->xalign;
|
|
switch(hdl->bpp) {
|
|
case 8:
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
*p++ = (UINT8)color;
|
|
} while(--r);
|
|
p += hdl->yalign - width;
|
|
} while(--remain);
|
|
break;
|
|
#ifdef SUPPORT_16BPP
|
|
case 16:
|
|
c16 = MAKE16PAL(color);
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
*(UINT16 *)p = (UINT16)c16;
|
|
p += 2;
|
|
} while(--r);
|
|
p += hdl->yalign - (width * 2);
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
case 24:
|
|
c24[0] = (UINT8)color;
|
|
c24[1] = (UINT8)(color >> 8);
|
|
c24[2] = (UINT8)(color >> 16);
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
p[0] = c24[0];
|
|
p[1] = c24[1];
|
|
p[2] = c24[2];
|
|
p += 3;
|
|
} while(--r);
|
|
p += hdl->yalign - (width * 3);
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
default:
|
|
TRACEOUT(("vram_filldat: unsupport %dbpp", hdl->bpp));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void vram_fillalpha(VRAMHDL hdl, const RECT_T *rect, UINT8 alpha) {
|
|
|
|
int ptr;
|
|
int width;
|
|
int height;
|
|
int pos;
|
|
int remain;
|
|
UINT8 *p;
|
|
|
|
if ((hdl == NULL) || (hdl->alpha == NULL)) {
|
|
return;
|
|
}
|
|
if (rect == NULL) {
|
|
p = hdl->ptr;
|
|
remain = hdl->scrnsize;
|
|
FillMemory(hdl->alpha, hdl->scrnsize, alpha);
|
|
}
|
|
else {
|
|
pos = max(rect->left, 0);
|
|
ptr = pos;
|
|
width = min(rect->right, hdl->width) - pos;
|
|
pos = max(rect->top, 0);
|
|
ptr += pos * hdl->width;
|
|
height = min(rect->bottom, hdl->height) - pos;
|
|
if ((width > 0) && (height > 0)) {
|
|
p = hdl->alpha + ptr;
|
|
remain = height;
|
|
do {
|
|
FillMemory(p, width, alpha);
|
|
p += hdl->width;
|
|
} while(--remain);
|
|
}
|
|
}
|
|
}
|
|
|
|
void vram_fillex(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha) {
|
|
|
|
int ptr;
|
|
int width;
|
|
int height;
|
|
int pos;
|
|
int remain;
|
|
UINT8 *p;
|
|
#ifdef SUPPORT_16BPP
|
|
int tmp;
|
|
int c16[3];
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
int c24[3];
|
|
#endif
|
|
|
|
if (hdl == NULL) {
|
|
return;
|
|
}
|
|
if (rect == NULL) {
|
|
p = hdl->ptr;
|
|
remain = hdl->scrnsize;
|
|
switch(hdl->bpp) {
|
|
#ifdef SUPPORT_16BPP
|
|
case 16:
|
|
tmp = MAKE16PAL(color);
|
|
c16[0] = tmp & B16MASK;
|
|
c16[1] = tmp & G16MASK;
|
|
c16[2] = tmp & R16MASK;
|
|
tmp = 64 - alpha;
|
|
do {
|
|
UINT s, d;
|
|
s = *(UINT16 *)p;
|
|
d = MAKEALPHA16s(c16[0], s, B16MASK, tmp, 6);
|
|
d |= MAKEALPHA16s(c16[1], s, G16MASK, tmp, 6);
|
|
d |= MAKEALPHA16s(c16[2], s, R16MASK, tmp, 6);
|
|
*(UINT16 *)p = (UINT16)d;
|
|
p += 2;
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
case 24:
|
|
c24[0] = color & 0xff;
|
|
c24[1] = (color >> 8) & 0xff;
|
|
c24[2] = (color >> 16) & 0xff;
|
|
do {
|
|
p[0] = (UINT8)MAKEALPHA24(p[0], c24[0], alpha, 6);
|
|
p[1] = (UINT8)MAKEALPHA24(p[1], c24[1], alpha, 6);
|
|
p[2] = (UINT8)MAKEALPHA24(p[2], c24[2], alpha, 6);
|
|
p += 3;
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
default:
|
|
TRACEOUT(("vram_fillex: unsupport %dbpp", hdl->bpp));
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
pos = max(rect->left, 0);
|
|
ptr = pos;
|
|
width = min(rect->right, hdl->width) - pos;
|
|
pos = max(rect->top, 0);
|
|
ptr += pos * hdl->width;
|
|
height = min(rect->bottom, hdl->height) - pos;
|
|
if ((width > 0) && (height > 0)) {
|
|
p = hdl->ptr;
|
|
p += ptr * hdl->xalign;
|
|
switch(hdl->bpp) {
|
|
#ifdef SUPPORT_16BPP
|
|
case 16:
|
|
tmp = MAKE16PAL(color);
|
|
c16[0] = tmp & B16MASK;
|
|
c16[1] = tmp & G16MASK;
|
|
c16[2] = tmp & R16MASK;
|
|
tmp = 64 - alpha;
|
|
remain = height;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
UINT s, d;
|
|
s = *(UINT16 *)p;
|
|
d = MAKEALPHA16s(c16[0], s, B16MASK, tmp, 6);
|
|
d |= MAKEALPHA16s(c16[1], s, G16MASK, tmp, 6);
|
|
d |= MAKEALPHA16s(c16[2], s, R16MASK, tmp, 6);
|
|
*(UINT16 *)p = (UINT16)d;
|
|
p += 2;
|
|
} while(--r);
|
|
p += hdl->yalign - (width * 2);
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
#ifdef SUPPORT_24BPP
|
|
case 24:
|
|
remain = height;
|
|
c24[0] = color & 0xff;
|
|
c24[1] = (color >> 8) & 0xff;
|
|
c24[2] = (color >> 16) & 0xff;
|
|
do {
|
|
int r = width;
|
|
do {
|
|
p[0] = (UINT8)MAKEALPHA24(p[0], c24[0], alpha, 6);
|
|
p[1] = (UINT8)MAKEALPHA24(p[1], c24[1], alpha, 6);
|
|
p[2] = (UINT8)MAKEALPHA24(p[2], c24[2], alpha, 6);
|
|
p += 3;
|
|
} while(--r);
|
|
p += hdl->yalign - (width * 3);
|
|
} while(--remain);
|
|
break;
|
|
#endif
|
|
default:
|
|
TRACEOUT(("vram_fillex: unsupport %dbpp", hdl->bpp));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VRAMHDL vram_resize(VRAMHDL base, int width, int height, int bpp) {
|
|
|
|
VRAMHDL ret;
|
|
RSZHDL rsz;
|
|
|
|
if (base == NULL) {
|
|
goto vrs_err1;
|
|
}
|
|
ret = vram_create(width, height, (base->alpha != NULL), bpp);
|
|
if (ret == NULL) {
|
|
goto vrs_err1;
|
|
}
|
|
rsz = resize(width, height, base->width, base->height);
|
|
if (rsz == NULL) {
|
|
goto vrs_err2;
|
|
}
|
|
(*rsz->func)(rsz, resize_gettype(bpp, base->bpp),
|
|
ret->ptr, ret->yalign, base->ptr, base->yalign);
|
|
if (base->alpha) {
|
|
(*rsz->func)(rsz, RSZFN_8BPP,
|
|
ret->alpha, ret->width, base->alpha, base->width);
|
|
}
|
|
_MFREE(rsz);
|
|
return(ret);
|
|
|
|
vrs_err2:
|
|
vram_destroy(ret);
|
|
|
|
vrs_err1:
|
|
return(NULL);
|
|
}
|
|
|
|
void vram_getrect(const VRAMHDL hdl, RECT_T *rct) {
|
|
|
|
int x, y;
|
|
|
|
if ((hdl) && (rct)) {
|
|
x = hdl->posx;
|
|
y = hdl->posy;
|
|
rct->left = x;
|
|
rct->top = y;
|
|
rct->right = x + hdl->width;
|
|
rct->bottom = y + hdl->height;
|
|
}
|
|
}
|
|
|
|
VRAMHDL vram_dupe(const VRAMHDL hdl) {
|
|
|
|
VRAMHDL ret = NULL;
|
|
int size;
|
|
int datsize;
|
|
|
|
if (hdl == NULL) {
|
|
goto vd_exit;
|
|
}
|
|
datsize = hdl->scrnsize * hdl->xalign;
|
|
size = sizeof(_VRAMHDL);
|
|
size += datsize;
|
|
if (hdl->alpha) {
|
|
size += hdl->scrnsize;
|
|
}
|
|
ret = (VRAMHDL)_MALLOC(size, "VRAM copy");
|
|
if (ret == NULL) {
|
|
goto vd_exit;
|
|
}
|
|
*ret = *hdl;
|
|
if (hdl->alpha) {
|
|
ret->alpha = (UINT8 *)(ret + 1);
|
|
CopyMemory(ret->alpha, hdl->alpha, hdl->scrnsize);
|
|
ret->ptr = ret->alpha + hdl->scrnsize;
|
|
}
|
|
else {
|
|
ret->ptr = (UINT8 *)(ret + 1);
|
|
}
|
|
CopyMemory(ret->ptr, hdl->ptr, datsize);
|
|
|
|
vd_exit:
|
|
return(ret);
|
|
}
|
|
|
|
BRESULT vram_cliprect(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct) {
|
|
|
|
if (vram == NULL) {
|
|
return(FAILURE);
|
|
}
|
|
if (rct == NULL) {
|
|
clip->left = 0;
|
|
clip->top = 0;
|
|
clip->right = vram->width;
|
|
clip->bottom = vram->height;
|
|
return(SUCCESS);
|
|
}
|
|
if ((rct->bottom <= 0) || (rct->right <= 0) ||
|
|
(rct->left >= vram->width) || (rct->top >= vram->height)) {
|
|
return(FAILURE);
|
|
}
|
|
clip->left = max(rct->left, 0);
|
|
clip->top = max(rct->top, 0);
|
|
clip->right = min(rct->right, vram->width);
|
|
clip->bottom = min(rct->bottom, vram->height);
|
|
if ((clip->top >= clip->bottom) || (clip->left >= clip->right)) {
|
|
return(FAILURE);
|
|
}
|
|
return(SUCCESS);
|
|
}
|
|
|
|
BRESULT vram_cliprectex(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct) {
|
|
|
|
if ((vram == NULL) || (clip == NULL)) {
|
|
return(FAILURE);
|
|
}
|
|
vram_getrect(vram, clip);
|
|
if (rct == NULL) {
|
|
return(SUCCESS);
|
|
}
|
|
clip->left = max(clip->left, rct->left);
|
|
clip->top = max(clip->top, rct->top);
|
|
clip->right = min(clip->right, rct->right);
|
|
clip->bottom = min(clip->bottom, rct->bottom);
|
|
if ((clip->left >= clip->right) || (clip->top >= clip->bottom)) {
|
|
return(FAILURE);
|
|
}
|
|
return(SUCCESS);
|
|
}
|
|
|