mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
686 lines
15 KiB
C++
686 lines
15 KiB
C++
|
|
/* GDI graphics renderer */
|
|
|
|
#include <windows.h>
|
|
#include "resource.h"
|
|
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#include "options.h"
|
|
#include "xwin.h"
|
|
#include "custom.h"
|
|
#include "drawing.h"
|
|
#include "render.h"
|
|
#include "win32.h"
|
|
#include "win32gfx.h"
|
|
#include "statusline.h"
|
|
#include "uae.h"
|
|
#include "direct3d.h"
|
|
#include "gfxfilter.h"
|
|
|
|
struct gdibm
|
|
{
|
|
bool active;
|
|
int x, y;
|
|
int width, height, depth;
|
|
int maxw, maxh;
|
|
HDC thdc;
|
|
HBITMAP hbm;
|
|
HGDIOBJ oldbm;
|
|
void *bits;
|
|
int pitch;
|
|
};
|
|
|
|
struct gdioverlay
|
|
{
|
|
struct gdioverlay *next;
|
|
int id;
|
|
int x, y;
|
|
struct gdibm tex;
|
|
};
|
|
|
|
struct gdistruct
|
|
{
|
|
int enabled;
|
|
int num;
|
|
int wwidth, wheight;
|
|
int depth;
|
|
HWND hwnd;
|
|
HDC hdc;
|
|
HGDIOBJ oldbm;
|
|
int statusbar_hx, statusbar_vx;
|
|
int ledwidth, ledheight;
|
|
struct gdibm bm;
|
|
struct gdibm buf;
|
|
struct gdibm osd;
|
|
struct gdibm cursor;
|
|
struct gdioverlay *extoverlays;
|
|
|
|
float cursor_x, cursor_y;
|
|
float cursor_mx, cursor_my;
|
|
bool cursor_v, cursor_scale;
|
|
|
|
RECT sr2, dr2, zr2;
|
|
int dmult, dmultxh, dmultxv, dmode;
|
|
int xoffset, yoffset;
|
|
float xmult, ymult;
|
|
int cursor_offset_x, cursor_offset_y;
|
|
|
|
int bmxoffset, bmyoffset;
|
|
int bmwidth, bmheight;
|
|
bool refreshneeded;
|
|
bool eraseneeded;
|
|
};
|
|
|
|
static struct gdistruct gdidata[MAX_AMIGAMONITORS];
|
|
|
|
static void gdi_restore(int monid, bool checkonly)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
}
|
|
|
|
static void setupscenecoords(struct gdistruct *gdi, int monid)
|
|
{
|
|
RECT sr, dr, zr;
|
|
static RECT sr2[MAX_AMIGAMONITORS], dr2[MAX_AMIGAMONITORS], zr2[MAX_AMIGAMONITORS];
|
|
|
|
getfilterrect2(gdi->num, &dr, &sr, &zr, gdi->wwidth, gdi->wheight, gdi->bm.width / gdi->dmult, gdi->bm.height / gdi->dmult, gdi->dmult, &gdi->dmode, gdi->bm.width, gdi->bm.height);
|
|
|
|
if (memcmp(&sr, &sr2[monid], sizeof RECT) || memcmp(&dr, &dr2[monid], sizeof RECT) || memcmp(&zr, &zr2[monid], sizeof RECT)) {
|
|
write_log(_T("POS (%d %d %d %d) - (%d %d %d %d)[%d,%d] (%d %d) S=%d*%d B=%d*%d\n"),
|
|
dr.left, dr.top, dr.right, dr.bottom,
|
|
sr.left, sr.top, sr.right, sr.bottom,
|
|
sr.right - sr.left, sr.bottom - sr.top,
|
|
zr.left, zr.top,
|
|
gdi->wwidth, gdi->wheight,
|
|
gdi->bm.width, gdi->bm.height);
|
|
sr2[monid] = sr;
|
|
dr2[monid] = dr;
|
|
zr2[monid] = zr;
|
|
}
|
|
|
|
gdi->sr2 = sr;
|
|
gdi->dr2 = dr;
|
|
gdi->zr2 = zr;
|
|
|
|
float dw = (float)dr.right - dr.left;
|
|
float dh = (float)dr.bottom - dr.top;
|
|
float w = (float)sr.right - sr.left;
|
|
float h = (float)sr.bottom - sr.top;
|
|
|
|
int tx = ((dr.right - dr.left) * gdi->bm.width) / (gdi->wwidth * 2);
|
|
int ty = ((dr.bottom - dr.top) * gdi->bm.height) / (gdi->wheight * 2);
|
|
|
|
float sw = dw / gdi->wwidth;
|
|
float sh = dh / gdi->wheight;
|
|
|
|
int xshift = -zr.left - sr.left;
|
|
int yshift = -zr.top - sr.top;
|
|
|
|
xshift -= ((sr.right - sr.left) - gdi->wwidth) / 2;
|
|
yshift -= ((sr.bottom - sr.top) - gdi->wheight) / 2;
|
|
|
|
gdi->xoffset = tx + xshift - gdi->wwidth / 2;
|
|
gdi->yoffset = ty + yshift - gdi->wheight / 2;
|
|
|
|
gdi->xmult = filterrectmult(gdi->wwidth, w, gdi->dmode);
|
|
gdi->ymult = filterrectmult(gdi->wheight, h, gdi->dmode);
|
|
|
|
gdi->cursor_offset_x = -zr.left;
|
|
gdi->cursor_offset_y = -zr.top;
|
|
|
|
sw *= gdi->wwidth;
|
|
sh *= gdi->wheight;
|
|
|
|
gdi->bmwidth = (int)(gdi->bm.width * gdi->xmult);
|
|
gdi->bmheight = (int)(gdi->bm.height * gdi->ymult);
|
|
|
|
int positionX, positionY;
|
|
int bw2 = gdi->bm.width;
|
|
int bh2 = gdi->bm.height;
|
|
int sw2 = gdi->wwidth;
|
|
int sh2 = gdi->wheight;
|
|
|
|
positionX = (sw2 - bw2) / 2 + gdi->xoffset;
|
|
positionY = (sh2 - bh2) / 2 + gdi->yoffset;
|
|
|
|
float left = sw2 / -2.0f;
|
|
left += positionX;
|
|
|
|
float top = sh2 / -2.0f;
|
|
top += positionY;
|
|
|
|
left *= gdi->xmult;
|
|
top *= gdi->ymult;
|
|
|
|
left += gdi->wwidth / 2.0f;
|
|
top += gdi->wheight / 2.0f;
|
|
|
|
gdi->bmxoffset = (int)left;
|
|
gdi->bmyoffset = (int)top;
|
|
|
|
gdi->eraseneeded = true;
|
|
}
|
|
|
|
static void gdi_clear(int monid)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
|
|
if (gdi->hdc) {
|
|
Rectangle(gdi->hdc, 0, 0, gdi->wwidth, gdi->wheight);
|
|
}
|
|
}
|
|
|
|
static void freesprite(struct gdistruct *gdi, struct gdibm *bm)
|
|
{
|
|
if (bm->thdc) {
|
|
if (bm->hbm) {
|
|
if (bm->oldbm) {
|
|
SelectObject(bm->thdc, bm->oldbm);
|
|
}
|
|
DeleteObject(bm->hbm);
|
|
}
|
|
bm->oldbm = NULL;
|
|
bm->hbm = NULL;
|
|
bm->bits = NULL;
|
|
DeleteDC(bm->thdc);
|
|
bm->thdc = NULL;
|
|
}
|
|
bm->active = false;
|
|
}
|
|
|
|
static void freetexture(int monid)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
freesprite(gdi, &gdi->bm);
|
|
if (gdi->hdc) {
|
|
ReleaseDC(gdi->hwnd, gdi->hdc);
|
|
gdi->hdc = NULL;
|
|
}
|
|
}
|
|
|
|
static bool allocsprite(struct gdistruct *gdi, struct gdibm *bm, int w, int h)
|
|
{
|
|
bm->thdc = CreateCompatibleDC(gdi->hdc);
|
|
if (bm->thdc) {
|
|
BITMAPV4HEADER bmi = { 0 };
|
|
bmi.bV4Size = sizeof(BITMAPINFOHEADER);
|
|
bmi.bV4Width = w;
|
|
bmi.bV4Height = -h;
|
|
bmi.bV4Planes = 1;
|
|
bmi.bV4V4Compression = BI_RGB;
|
|
bmi.bV4BitCount = gdi->depth;
|
|
bm->width = w;
|
|
bm->height = h;
|
|
bm->depth = gdi->depth;
|
|
bm->pitch = ((w * bmi.bV4BitCount + 31) / 32) * 4;
|
|
bmi.bV4SizeImage = bm->pitch * h;
|
|
bm->hbm = CreateDIBSection(gdi->hdc, (const BITMAPINFO*)&bmi, DIB_RGB_COLORS, &bm->bits, NULL, 0);
|
|
if (bm->hbm) {
|
|
bm->oldbm = SelectObject(bm->thdc, bm->hbm);
|
|
SelectObject(bm->thdc, GetStockObject(DC_PEN));
|
|
SelectObject(bm->thdc, GetStockObject(DC_BRUSH));
|
|
SetDCPenColor(bm->thdc, RGB(0, 0, 0));
|
|
SetDCBrushColor(bm->thdc, RGB(0, 0, 0));
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool gdi_alloctexture(int monid, int w, int h)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
|
|
if (w < 0 || h < 0) {
|
|
if (gdi->bm.width == -w && gdi->bm.height == -h && gdi->hdc) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
freetexture(monid);
|
|
|
|
gdi->hdc = GetDC(gdi->hwnd);
|
|
if (gdi->hdc) {
|
|
SelectObject(gdi->hdc, GetStockObject(DC_PEN));
|
|
SelectObject(gdi->hdc, GetStockObject(DC_BRUSH));
|
|
SetDCPenColor(gdi->hdc, RGB(0, 0, 0));
|
|
SetDCBrushColor(gdi->hdc, RGB(0, 0, 0));
|
|
if (allocsprite(gdi, &gdi->bm, w, h)) {
|
|
gdi->dmult = S2X_getmult(monid);
|
|
setupscenecoords(gdi, monid);
|
|
return true;
|
|
}
|
|
}
|
|
freetexture(monid);
|
|
return false;
|
|
}
|
|
|
|
static void updateleds(struct gdistruct *gdi)
|
|
{
|
|
static uae_u32 rc[256], gc[256], bc[256], a[256];
|
|
static int done;
|
|
int osdx, osdy;
|
|
|
|
if (!done) {
|
|
for (int i = 0; i < 256; i++) {
|
|
rc[i] = i << 16;
|
|
gc[i] = i << 8;
|
|
bc[i] = i << 0;
|
|
a[i] = i << 24;
|
|
}
|
|
done = 1;
|
|
}
|
|
|
|
|
|
if (gdi->osd.bits == NULL || gdi != gdidata)
|
|
return;
|
|
|
|
statusline_getpos(gdi->num, &osdx, &osdy, gdi->wwidth, gdi->wheight);
|
|
gdi->osd.x = osdx;
|
|
gdi->osd.y = osdy;
|
|
|
|
for (int y = 0; y < gdi->osd.height; y++) {
|
|
uae_u8 *buf = (uae_u8*)gdi->osd.bits + y * gdi->osd.pitch;
|
|
statusline_single_erase(gdi->num, buf, gdi->osd.depth / 8, y, gdi->ledwidth);
|
|
}
|
|
statusline_render(gdi->num, (uae_u8*)gdi->osd.bits, gdi->osd.depth / 8, gdi->osd.pitch, gdi->ledwidth, gdi->ledheight, rc, gc, bc, a);
|
|
|
|
for (int y = 0; y < gdi->osd.height; y++) {
|
|
uae_u8 *buf = (uae_u8*)gdi->osd.bits + y * gdi->osd.pitch;
|
|
draw_status_line_single(gdi->num, buf, gdi->osd.depth / 8, y, gdi->ledwidth, rc, gc, bc, a);
|
|
}
|
|
}
|
|
|
|
static void gdi_guimode(int monid, int guion)
|
|
{
|
|
}
|
|
|
|
static uae_u8 *gdi_locktexture(int monid, int *pitch, int *width, int *height, int fullupdate)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
if (gdi->bm.bits) {
|
|
*pitch = gdi->bm.pitch;
|
|
if (height)
|
|
*height = gdi->bm.height;
|
|
if (width)
|
|
*width = gdi->bm.width;
|
|
return (uae_u8*)gdi->bm.bits;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void gdi_unlocktexture(int monid, int y_start, int y_end)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
|
|
struct AmigaMonitor *mon = &AMonitors[monid];
|
|
bool rtg = WIN32GFX_IsPicassoScreen(mon);
|
|
if (((currprefs.leds_on_screen & STATUSLINE_CHIPSET) && !rtg) || ((currprefs.leds_on_screen & STATUSLINE_RTG) && rtg)) {
|
|
updateleds(gdi);
|
|
gdi->osd.active = true;
|
|
} else {
|
|
gdi->osd.active = false;
|
|
}
|
|
}
|
|
|
|
static void gdi_flushtexture(int monid, int miny, int maxy)
|
|
{
|
|
}
|
|
|
|
static bool gdi_renderframe(int monid, int mode, bool immediate)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
|
|
if (gdi->bm.hbm) {
|
|
setupscenecoords(gdi, monid);
|
|
}
|
|
return gdi->bm.hbm != NULL;
|
|
}
|
|
|
|
static void gdi_paint(void)
|
|
{
|
|
for (int monid = 0; monid < MAX_AMIGAMONITORS; monid++) {
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
if (!gdi->refreshneeded) {
|
|
continue;
|
|
}
|
|
gdi->refreshneeded = false;
|
|
|
|
if (gdi->eraseneeded) {
|
|
Rectangle(gdi->buf.thdc, 0, 0, gdi->buf.width, gdi->buf.height);
|
|
gdi->eraseneeded = false;
|
|
}
|
|
|
|
if (gdi->bm.hbm) {
|
|
StretchBlt(gdi->buf.thdc, gdi->bmxoffset, gdi->bmyoffset, gdi->bmwidth, gdi->bmheight, gdi->bm.thdc, 0, 0, gdi->bm.width, gdi->bm.height, SRCCOPY);
|
|
}
|
|
if (gdi->cursor.active && gdi->cursor.hbm) {
|
|
int bx = gdi->bmxoffset;
|
|
int by = gdi->bmyoffset;
|
|
int x = gdi->cursor.x;
|
|
int y = gdi->cursor.y;
|
|
int cx = 0;
|
|
int cy = 0;
|
|
int cw = CURSORMAXWIDTH;
|
|
int ch = CURSORMAXHEIGHT;
|
|
if (gdi->cursor.x < bx) {
|
|
int d = bx - gdi->cursor.x;
|
|
cx += d;
|
|
cw -= d;
|
|
x += d;
|
|
}
|
|
if (gdi->cursor.y < by) {
|
|
int d = by - gdi->cursor.y;
|
|
cy += d;
|
|
ch -= d;
|
|
y += d;
|
|
}
|
|
if (x + cw > gdi->cursor.maxw) {
|
|
cw -= (x + cw) - gdi->cursor.maxw;
|
|
}
|
|
if (y + ch > gdi->cursor.maxh) {
|
|
ch -= (y + ch) - gdi->cursor.maxh;
|
|
}
|
|
if (cw > 0 && ch > 0) {
|
|
TransparentBlt(gdi->buf.thdc, x, y, (int)(cw * gdi->xmult), (int)(ch * gdi->ymult), gdi->cursor.thdc, cx, cy, cw, ch, 0xfe00fe);
|
|
}
|
|
}
|
|
if (gdi->osd.active && gdi->osd.hbm) {
|
|
TransparentBlt(gdi->buf.thdc, gdi->osd.x, gdi->osd.y, gdi->ledwidth, gdi->ledheight, gdi->osd.thdc, 0, 0, gdi->ledwidth, gdi->ledheight, 0x000000);
|
|
}
|
|
struct gdioverlay *ov = gdi->extoverlays;
|
|
while (ov) {
|
|
if (ov->tex.bits) {
|
|
TransparentBlt(gdi->buf.thdc, ov->x, ov->y, ov->tex.width, ov->tex.height, ov->tex.thdc, 0, 0, ov->tex.width, ov->tex.height, 0xfe00fe);
|
|
}
|
|
ov = ov->next;
|
|
}
|
|
|
|
BitBlt(gdi->hdc, 0, 0, gdi->wwidth, gdi->wheight, gdi->buf.thdc, 0, 0, SRCCOPY);
|
|
}
|
|
}
|
|
|
|
static void gdi_showframe(int monid)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
gdi->refreshneeded = true;
|
|
RECT r;
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = gdi->wwidth;
|
|
r.bottom = gdi->wheight;
|
|
InvalidateRect(gdi->hwnd, &r, FALSE);
|
|
}
|
|
|
|
static void gdi_refresh(int monid)
|
|
{
|
|
gdi_clear(monid);
|
|
gdi_showframe(monid);
|
|
}
|
|
|
|
void gdi_free(int monid, bool immediate)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
gdi->enabled = 0;
|
|
freetexture(monid);
|
|
freesprite(gdi, &gdi->osd);
|
|
freesprite(gdi, &gdi->cursor);
|
|
struct gdioverlay *ov = gdi->extoverlays;
|
|
while (ov) {
|
|
struct gdioverlay *next = ov->next;
|
|
if (ov->tex.bits) {
|
|
freesprite(gdi, &ov->tex);
|
|
}
|
|
xfree(ov);
|
|
ov = next;
|
|
}
|
|
gdi->extoverlays = NULL;
|
|
}
|
|
|
|
static const TCHAR *gdi_init(HWND ahwnd, int monid, int w_w, int w_h, int depth, int *freq, int mmulth, int mmultv, int *errp)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
|
|
if (isfullscreen() > 0) {
|
|
*errp = 2;
|
|
return _T("GDI fullscreen not supported");
|
|
}
|
|
|
|
gdi->hwnd = ahwnd;
|
|
gdi->depth = depth;
|
|
gdi->wwidth = w_w;
|
|
gdi->wheight = w_h;
|
|
if (allocsprite(gdi, &gdi->buf, gdi->wwidth, gdi->wheight)) {
|
|
gdi->statusbar_hx = gdi->statusbar_vx = statusline_set_multiplier(monid, gdi->wwidth, gdi->wheight) / 100;
|
|
gdi->ledwidth = gdi->wwidth;
|
|
gdi->ledheight = TD_TOTAL_HEIGHT * gdi->statusbar_vx;
|
|
allocsprite(gdi, &gdi->osd, gdi->ledwidth, gdi->ledheight);
|
|
allocsprite(gdi, &gdi->cursor, CURSORMAXWIDTH, CURSORMAXHEIGHT);
|
|
gdi->enabled = 1;
|
|
write_log(_T("GDI mode initialized %d*%d*%d\n"), w_w, w_h, depth);
|
|
return NULL;
|
|
}
|
|
|
|
*errp = 1;
|
|
return _T("failed to allocate buffer");
|
|
}
|
|
|
|
static HDC gdi_getDC(int monid, HDC hdc)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
|
|
if (!hdc) {
|
|
return gdi->hdc;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static int gdi_isenabled(int monid)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
return gdi->enabled ? -1 : 0;
|
|
}
|
|
|
|
static bool gdi_setcursor(int monid, int x, int y, int width, int height, float mx, float my, bool visible, bool noscale)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
int cx, cy;
|
|
|
|
if (gdi->depth < 32) {
|
|
return false;
|
|
}
|
|
|
|
if (width < 0 || height < 0) {
|
|
return true;
|
|
}
|
|
|
|
if (width && height) {
|
|
cx = (int)((float)x * mx * gdi->xmult + gdi->cursor_offset_x * gdi->ymult + 0.5f);
|
|
cy = (int)((float)y * my * gdi->ymult + gdi->cursor_offset_y * gdi->xmult + 0.5f);
|
|
} else {
|
|
cx = cy = 0;
|
|
}
|
|
if (cx < 0) {
|
|
cx = 0;
|
|
}
|
|
if (cy < 0) {
|
|
cy = 0;
|
|
}
|
|
gdi->cursor.x = cx;
|
|
gdi->cursor.y = cy;
|
|
gdi->cursor.maxw = (int)((float)gdi->bmwidth * mx * gdi->xmult + gdi->cursor_offset_x * gdi->ymult + 0.5f);
|
|
gdi->cursor.maxh = (int)((float)gdi->bmheight * my * gdi->ymult + gdi->cursor_offset_y * gdi->xmult + 0.5f);
|
|
gdi->cursor_scale = !noscale;
|
|
gdi->cursor.active = visible;
|
|
return true;
|
|
}
|
|
|
|
static uae_u8 *gdi_setcursorsurface(int monid, bool query, int *pitch)
|
|
{
|
|
struct gdistruct* gdi = &gdidata[monid];
|
|
|
|
if (query) {
|
|
return (uae_u8 *)gdi->cursor.bits;
|
|
}
|
|
|
|
if (gdi->depth < 32) {
|
|
return NULL;
|
|
}
|
|
|
|
if (pitch) {
|
|
*pitch = gdi->cursor.pitch;
|
|
return (uae_u8*)gdi->cursor.bits;
|
|
}
|
|
for (int y = 0; y < CURSORMAXHEIGHT; y++) {
|
|
for (int x = 0; x < CURSORMAXWIDTH; x++) {
|
|
uae_u32 *p = (uae_u32*)((uae_u8*)gdi->cursor.bits + gdi->cursor.pitch * y + x * 4);
|
|
uae_u32 v = *p;
|
|
if ((v & 0xff000000) == 0x00000000) {
|
|
*p = 0xfe00fe;
|
|
} else {
|
|
*p = v & 0xffffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static bool gdi_extoverlay(struct extoverlay *ext, int monid)
|
|
{
|
|
struct gdistruct *gdi = &gdidata[monid];
|
|
struct gdioverlay *ov, *ovprev, *ov2;
|
|
struct gdibm *s = NULL;
|
|
|
|
if (gdi->depth < 32) {
|
|
return false;
|
|
}
|
|
|
|
gdi->eraseneeded = true;
|
|
|
|
ov = gdi->extoverlays;
|
|
ovprev = NULL;
|
|
while (ov) {
|
|
if (ov->id == ext->idx) {
|
|
s = &ov->tex;
|
|
break;
|
|
}
|
|
ovprev = ov;
|
|
ov = ov->next;
|
|
}
|
|
|
|
if (!s && (ext->width <= 0 || ext->height <= 0))
|
|
return false;
|
|
|
|
if (!ext->data && s && (ext->width == 0 || ext->height == 0)) {
|
|
ov->x = ext->xpos;
|
|
ov->y = ext->ypos;
|
|
return true;
|
|
}
|
|
|
|
if (ov && s) {
|
|
if (ovprev) {
|
|
ovprev->next = ov->next;
|
|
} else {
|
|
gdi->extoverlays = ov->next;
|
|
}
|
|
freesprite(gdi, s);
|
|
xfree(ov);
|
|
if (ext->width <= 0 || ext->height <= 0)
|
|
return true;
|
|
}
|
|
|
|
if (ext->width <= 0 || ext->height <= 0 || !ext->data)
|
|
return false;
|
|
|
|
ov = xcalloc(gdioverlay, 1);
|
|
if (!ov) {
|
|
return false;
|
|
}
|
|
if (!allocsprite(gdi, &ov->tex, ext->width, ext->height)) {
|
|
xfree(ov);
|
|
return false;
|
|
}
|
|
|
|
s = &ov->tex;
|
|
ov->id = ext->idx;
|
|
|
|
ov2 = gdi->extoverlays;
|
|
ovprev = NULL;
|
|
for (;;) {
|
|
if (ov2 == NULL || ov2->id >= ov->id) {
|
|
if (ov2 == gdi->extoverlays) {
|
|
gdi->extoverlays = ov;
|
|
ov->next = ov2;
|
|
} else {
|
|
ov->next = ovprev->next;
|
|
ovprev->next = ov;
|
|
}
|
|
break;
|
|
}
|
|
ovprev = ov2;
|
|
ov2 = ov2->next;
|
|
}
|
|
|
|
ov->x = ext->xpos;
|
|
ov->y = ext->ypos;
|
|
|
|
for (int y = 0; y < ext->height; y++) {
|
|
for (int x = 0; x < ext->width; x++) {
|
|
uae_u32 *sp = (uae_u32*)(ext->data + ext->width * y * 4 + x * 4);
|
|
uae_u32 *p = (uae_u32*)((uae_u8*)s->bits + s->pitch * y + x * 4);
|
|
uae_u32 v = *sp;
|
|
if ((v & 0xff000000) == 0x00000000) {
|
|
*p = 0xfe00fe;
|
|
} else {
|
|
*p = v & 0xffffff;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void gdi_select(void)
|
|
{
|
|
for (int i = 0; i < MAX_AMIGAMONITORS; i++) {
|
|
gdidata[i].num = i;
|
|
}
|
|
|
|
D3D_free = gdi_free;
|
|
D3D_init = gdi_init;
|
|
|
|
D3D_renderframe = gdi_renderframe;
|
|
D3D_alloctexture = gdi_alloctexture;
|
|
D3D_refresh = gdi_refresh;
|
|
D3D_restore = gdi_restore;
|
|
|
|
D3D_locktexture = gdi_locktexture;
|
|
D3D_unlocktexture = gdi_unlocktexture;
|
|
D3D_flushtexture = gdi_flushtexture;
|
|
|
|
D3D_showframe = gdi_showframe;
|
|
D3D_showframe_special = NULL;
|
|
D3D_guimode = gdi_guimode;
|
|
D3D_getDC = gdi_getDC;
|
|
D3D_isenabled = gdi_isenabled;
|
|
D3D_clear = gdi_clear;
|
|
D3D_canshaders = NULL;
|
|
D3D_goodenough = NULL;
|
|
D3D_setcursor = gdi_setcursor;
|
|
D3D_setcursorsurface = gdi_setcursorsurface;
|
|
D3D_getrefreshrate = NULL;
|
|
D3D_resize = NULL;
|
|
D3D_change = NULL;
|
|
D3D_getscalerect = NULL;
|
|
D3D_run = NULL;
|
|
D3D_debug = NULL;
|
|
D3D_led = NULL;
|
|
D3D_getscanline = NULL;
|
|
D3D_extoverlay = gdi_extoverlay;
|
|
D3D_paint = gdi_paint;
|
|
}
|