2024-04-16 03:43:29 +00:00
|
|
|
/*
|
|
|
|
* $Logfile: /DescentIII/Main/ddgr_win32/ddgrWin32GDI.cpp $
|
|
|
|
* $Revision: 10 $
|
|
|
|
* $Date: 10/02/98 11:15a $
|
|
|
|
* $Author: Jeff $
|
|
|
|
*
|
|
|
|
* DDGR v2.0 GDI(X) implementation
|
|
|
|
*
|
|
|
|
* $Log: /DescentIII/Main/ddgr_win32/ddgrWin32GDI.cpp $
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 10 10/02/98 11:15a Jeff
|
|
|
|
* added HBITMAP, HFONT and HBRUSH type casts where needed to satisfy the
|
|
|
|
* compiler
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 9 6/02/98 12:46p Samir
|
|
|
|
* removed restriction of ddgr system when going to true-color
|
|
|
|
* resolutions.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 8 4/23/98 6:38p Jason
|
|
|
|
* made bitmaps use 1555 format
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 7 4/09/98 11:00a Samir
|
|
|
|
* took out assertion in ddgr_gdi_Close that caused errors and assertions
|
|
|
|
* to 'crap' out.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 6 11/14/97 12:32p Samir
|
|
|
|
* DirectDraw works under GDIX windowed subsystem (NORMAL cooperative
|
|
|
|
* mode).
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 5 9/23/97 12:15p Jason
|
|
|
|
* fixed color bug
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 4 9/12/97 4:13p Samir
|
|
|
|
* Added some private data access functions and more DirectX
|
|
|
|
* functionality.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 3 8/12/97 10:43p Matt
|
|
|
|
* Fixed RGB conversion bug
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 5 6/16/97 4:46p Samir
|
|
|
|
* OpenGL works in window too.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 4 6/13/97 3:01p Samir
|
|
|
|
* Fixed flip assertions and OpenGL imp.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 3 6/13/97 1:24p Samir
|
|
|
|
* FlipVideo doesn't flip when no backbuffer, so just do nothing.
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 2 6/13/97 12:24p Samir
|
|
|
|
* Fixed OpenGLDC hack and removed assert in lock if data ptr = NULL
|
2024-04-16 18:56:40 +00:00
|
|
|
*
|
2024-04-16 03:43:29 +00:00
|
|
|
* 1 6/12/97 6:33p Samir
|
|
|
|
* Initial revision
|
|
|
|
*
|
|
|
|
* $NoKeywords: $
|
|
|
|
*/
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
#include "DDAccess.h" // Allow this module full DD access
|
2024-04-16 03:43:29 +00:00
|
|
|
#include "ddgrWin32.h"
|
|
|
|
#include "ddgrWin32GDI.h"
|
|
|
|
#include "Application.h"
|
|
|
|
#include "mono.h"
|
|
|
|
#include "pserror.h"
|
|
|
|
#include "gr.h"
|
|
|
|
|
|
|
|
/* Global Library Data
|
|
|
|
*/
|
|
|
|
tDDGRGDIInternalData DDGR_GDI_lib_data;
|
|
|
|
|
|
|
|
/* Primary Interface Functions
|
2024-04-16 18:56:40 +00:00
|
|
|
*/
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// initializes the objects needed to use GDI
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_Init(oeApplication *app, bool fullscreen, bool ddraw) {
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
GDI_DATA(fullscreen) = fullscreen;
|
|
|
|
GDI_DATA(hPrimaryWnd) = (HWND)((oeWin32Application *)app)->m_hWnd;
|
|
|
|
|
|
|
|
GDI_DATA(lpDD) = NULL;
|
|
|
|
if (ddraw) {
|
|
|
|
hres = DirectDrawCreate(NULL, &GDI_DATA(lpDD), NULL);
|
|
|
|
if (hres != DD_OK) {
|
|
|
|
ddgr_PushError("Failure to initialize DirectDraw driver (%d)", LOWORD(hres));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize DirectDraw exclusive system if we're going fullscreen, and GDIX system
|
|
|
|
if (GDI_DATA(fullscreen)) {
|
|
|
|
if (ddraw) {
|
|
|
|
hres = GDI_DATA(lpDD)->SetCooperativeLevel(GDI_DATA(hPrimaryWnd),
|
|
|
|
DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
|
|
|
|
|
|
|
|
if (hres != DD_OK) {
|
|
|
|
ddgr_PushError("Failed to set DirectDraw fullscreen access level (%d)", LOWORD(hres));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// grab all device modes for the current display device.
|
|
|
|
unsigned i;
|
|
|
|
for (i = 0; i < GDI_MAX_DEVMODES; i++) {
|
|
|
|
if (EnumDisplaySettings(NULL, i, &GDI_DATA(devmodes[i])) == FALSE) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
HDC hdc = GetDC(GDI_DATA(hPrimaryWnd));
|
|
|
|
|
|
|
|
if (GDI_DATA(devmodes[i].dmBitsPerPel) == (uint)GetDeviceCaps(hdc, BITSPIXEL) &&
|
|
|
|
GDI_DATA(devmodes[i].dmPelsWidth) == (uint)GetDeviceCaps(hdc, HORZRES) &&
|
|
|
|
GDI_DATA(devmodes[i].dmPelsHeight) == (uint)GetDeviceCaps(hdc, VERTRES))
|
|
|
|
GDI_DATA(olddispmode) = i;
|
|
|
|
|
|
|
|
ReleaseDC(GDI_DATA(hPrimaryWnd), hdc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GDI_DATA(ddraw) = ddraw;
|
|
|
|
} else {
|
|
|
|
if (ddraw) {
|
|
|
|
hres = GDI_DATA(lpDD)->SetCooperativeLevel(GDI_DATA(hPrimaryWnd), DDSCL_NORMAL);
|
|
|
|
if (hres != DD_OK) {
|
|
|
|
ddgr_PushError("Failed to set DirectDraw normal access level (%d)", LOWORD(hres));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GDI_DATA(hOffscreenDC) = NULL;
|
|
|
|
GDI_DATA(vidrefs) = 0; // reset video reference count.
|
|
|
|
GDI_DATA(init) = true;
|
|
|
|
|
|
|
|
mprintf((0, "GDI system initialized.\n"));
|
|
|
|
|
|
|
|
return true;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Deinitialized GDI objects
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void ddgr_gdi_Close() {
|
|
|
|
if (GDI_DATA(hOffscreenDC)) {
|
|
|
|
DeleteDC(GDI_DATA(hOffscreenDC));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GDI_DATA(fullscreen)) {
|
|
|
|
if (GDI_DATA(ddraw)) {
|
|
|
|
// For full screen, deinitialize directdraw/
|
|
|
|
if (GDI_DATA(lpDD)) {
|
|
|
|
GDI_DATA(lpDD)->RestoreDisplayMode();
|
|
|
|
GDI_DATA(lpDD)->Release();
|
|
|
|
}
|
|
|
|
GDI_DATA(lpDD) = NULL;
|
|
|
|
} else {
|
|
|
|
// do a ChangeDisplaySettings to old mode.
|
|
|
|
LONG lres;
|
|
|
|
GDI_DATA(devmodes[GDI_DATA(olddispmode)]).dmFields =
|
|
|
|
DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
|
|
|
|
|
|
|
|
lres = ChangeDisplaySettings(&GDI_DATA(devmodes[GDI_DATA(olddispmode)]), 0);
|
|
|
|
ASSERT(lres == DISP_CHANGE_SUCCESSFUL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GDI_DATA(hPrimaryWnd) = NULL;
|
|
|
|
GDI_DATA(init) = false;
|
|
|
|
|
|
|
|
mprintf((0, "GDI system closed.\n"));
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Initializes the video surface for blting
|
|
|
|
// note that is the surface specified is a back buffer by sf->flags, then we need
|
|
|
|
// to create a GDI bitmap for the back buffer, and our visible screen is the front buffer
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_surf_InitVideo(ddgr_surface *sf) {
|
|
|
|
tGDISurface *gdisf, *gdisf2;
|
|
|
|
|
|
|
|
// we need to create a DC for our GDI bitmaps if this is first ref to video surface.
|
|
|
|
if (GDI_DATA(vidrefs) == 0) {
|
|
|
|
// if we are in fullscreen, do display mode change
|
|
|
|
HDC hdc;
|
|
|
|
|
|
|
|
if (GDI_DATA(fullscreen)) {
|
|
|
|
if (GDI_DATA(ddraw)) {
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
hres = GDI_DATA(lpDD)->SetDisplayMode(sf->w, sf->h, sf->bpp);
|
|
|
|
if (hres != DD_OK) {
|
|
|
|
ddgr_PushError("Unable to set DirectDraw display mode in fullscreen (%d)\n", LOWORD(hres));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// grab all device modes for the current display device.
|
|
|
|
unsigned i;
|
|
|
|
for (i = 0; i < GDI_MAX_DEVMODES; i++) {
|
|
|
|
LONG lres;
|
|
|
|
if ((int)GDI_DATA(devmodes[i].dmBitsPerPel) == sf->bpp && (int)GDI_DATA(devmodes[i].dmPelsWidth) == sf->w &&
|
|
|
|
(int)GDI_DATA(devmodes[i].dmPelsHeight) == sf->h) {
|
|
|
|
// do a ChangeDisplaySettings to old mode.
|
|
|
|
GDI_DATA(devmodes[i]).dmFields =
|
|
|
|
DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
|
|
|
|
|
|
|
|
lres = ChangeDisplaySettings(&GDI_DATA(devmodes[i]), 0);
|
|
|
|
ASSERT(lres == DISP_CHANGE_SUCCESSFUL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// HACKS FOR OPENGL, WILL CHANGE SOON.
|
|
|
|
hdc = CreateCompatibleDC(NULL);
|
|
|
|
if (hdc == NULL) {
|
|
|
|
ddgr_PushError("Unable to create offscreen device context (%x).", GetLastError());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
GDI_DATA(hOffscreenDC) = hdc;
|
|
|
|
}
|
|
|
|
|
|
|
|
GDI_DATA(vidrefs)++; // increment vidref count
|
|
|
|
|
|
|
|
gdisf = new tGDISurface;
|
|
|
|
gdisf->hbm = NULL;
|
|
|
|
gdisf->data = NULL;
|
|
|
|
gdisf->rowsize = NULL;
|
|
|
|
gdisf->hwnd = NULL;
|
|
|
|
|
|
|
|
// this means that we are capturing the screen, not creating a screen.
|
|
|
|
// get the screen's width and height and bitdepth
|
|
|
|
if (sf->flags == 0) {
|
|
|
|
sf->w = (int)GetDeviceCaps(GDI_DATA(hOffscreenDC), HORZRES);
|
|
|
|
sf->h = (int)GetDeviceCaps(GDI_DATA(hOffscreenDC), VERTRES);
|
|
|
|
sf->bpp = (int)GetDeviceCaps(GDI_DATA(hOffscreenDC), BITSPIXEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
HDC hdc = GetDC(NULL);
|
|
|
|
int tbpp = GetDeviceCaps(hdc, BITSPIXEL);
|
|
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
|
|
|
|
if (tbpp < sf->bpp) {
|
|
|
|
ddgr_PushError("Desktop color depth must be set to a %d-bit color mode or greater.\n", sf->bpp);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we create a dummy surface for the screen's back buffer, or our accessable buffer
|
|
|
|
// specifying SURFFLAG_BACKBUFFER ensures that we create a GDI bitmap of size requested
|
|
|
|
// in 'sf' and it will be our renderable bitmap, or OUR primary render buffer
|
|
|
|
if (sf->flags & SURFFLAG_BACKBUFFER) {
|
|
|
|
ddgr_surface back_sf;
|
|
|
|
back_sf.w = sf->w;
|
|
|
|
back_sf.h = sf->h;
|
|
|
|
back_sf.bpp = sf->bpp;
|
|
|
|
back_sf.type = SURFTYPE_GENERIC;
|
|
|
|
|
|
|
|
if (!ddgr_gdi_surf_Create(&back_sf)) {
|
|
|
|
ddgr_PushError((0, "Failed to create back buffer <%s>", sf->name));
|
|
|
|
delete gdisf;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set our front buffer to this newly created surface and delete the gdi bitmap object
|
|
|
|
gdisf2 = (tGDISurface *)back_sf.obj;
|
|
|
|
gdisf->hbm = gdisf2->hbm;
|
|
|
|
gdisf->data = gdisf2->data;
|
|
|
|
gdisf->rowsize = gdisf2->rowsize;
|
|
|
|
gdisf->backbuffer = true;
|
|
|
|
delete gdisf2;
|
|
|
|
} else {
|
|
|
|
gdisf->hbm = NULL; // this is really just the screen.
|
|
|
|
gdisf->backbuffer = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gdisf->hwnd = GDI_DATA(hPrimaryWnd);
|
|
|
|
|
|
|
|
sf->obj = (void *)gdisf;
|
|
|
|
|
|
|
|
return true;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// deinitializes the DC created in InitVideo
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void ddgr_gdi_surf_CloseVideo(ddgr_surface *sf) {
|
|
|
|
tGDISurface *bm = (tGDISurface *)sf->obj;
|
|
|
|
|
|
|
|
ASSERT(GDI_DATA(vidrefs) > 0);
|
|
|
|
|
|
|
|
GDI_DATA(vidrefs)--;
|
|
|
|
if (GDI_DATA(vidrefs) == 0) {
|
|
|
|
if (GDI_DATA(fullscreen)) {
|
|
|
|
}
|
|
|
|
// HACK for OPENGL support.
|
|
|
|
DeleteDC(GDI_DATA(hOffscreenDC));
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
if (sf->flags & SURFFLAG_BACKBUFFER)
|
|
|
|
DeleteObject(bm->hbm); // eliminate back buffer
|
|
|
|
|
|
|
|
delete bm;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// flip, does absolutely nothing
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_surf_FlipVideo(ddgr_surface *sf) {
|
|
|
|
HBITMAP old_bmp, h_sbm;
|
|
|
|
HDC hdc_dest;
|
|
|
|
RECT rect;
|
|
|
|
int dw, dh;
|
|
|
|
tGDISurface *bm = (tGDISurface *)sf->obj;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
ASSERT(bm->hwnd != NULL);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
// don't give an error if there's no backbuffer.
|
|
|
|
if (!bm->backbuffer)
|
|
|
|
return true;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
h_sbm = bm->hbm;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
// if we associated another window with our screem, then make sure their DC is the dest.
|
|
|
|
// other wise, use our base window's DC for destination, and select our front buffer as the
|
|
|
|
// source bitmap into our driver's DC.
|
|
|
|
// if (bm->hwnd == NULL) {
|
|
|
|
// hdc_dest = GetDC(GDI_DATA(hwnd));
|
|
|
|
// GetClientRect(GDI_DATA(hwnd),&rect);
|
|
|
|
// }
|
|
|
|
// else {
|
|
|
|
hdc_dest = GetDC(bm->hwnd);
|
|
|
|
GetClientRect(bm->hwnd, &rect);
|
|
|
|
// }
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
dw = rect.right - rect.left;
|
|
|
|
dh = rect.bottom - rect.top;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
old_bmp = (HBITMAP)SelectObject(GDI_DATA(hOffscreenDC), h_sbm);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
BOOL bltres = BitBlt(hdc_dest, 0, 0, dw, dh, GDI_DATA(hOffscreenDC), 0, 0, SRCCOPY);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
SelectObject(GDI_DATA(hOffscreenDC), old_bmp);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
ReleaseDC(bm->hwnd, hdc_dest);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
return (bltres) ? true : false;
|
|
|
|
}
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Creates a GDI DIBitmap
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_surf_Create(ddgr_surface *sf) {
|
|
|
|
tGDISurface *bm;
|
|
|
|
|
|
|
|
// set up bitmap header
|
|
|
|
int nw = sf->w;
|
|
|
|
if (nw % 4)
|
|
|
|
nw = ((sf->w / 4) * 4) + 4;
|
|
|
|
|
|
|
|
bm = new tGDISurface;
|
|
|
|
|
|
|
|
if (sf->bpp == BPP_8) {
|
|
|
|
tDIBHeader8 header;
|
|
|
|
|
|
|
|
header.bmi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
header.bmi.biWidth = nw;
|
|
|
|
header.bmi.biHeight = -sf->h; // Always a top down bitmap!!
|
|
|
|
header.bmi.biPlanes = 1;
|
|
|
|
header.bmi.biBitCount = sf->bpp;
|
|
|
|
header.bmi.biCompression = BI_BITFIELDS;
|
|
|
|
header.bmi.biSizeImage = 0;
|
|
|
|
header.bmi.biXPelsPerMeter = 0;
|
|
|
|
header.bmi.biYPelsPerMeter = 0;
|
|
|
|
header.bmi.biClrUsed = 0;
|
|
|
|
header.bmi.biClrImportant = 0;
|
|
|
|
|
|
|
|
bm->hbm = CreateDIBSection(GDI_DATA(hOffscreenDC), (BITMAPINFO *)&header, DIB_RGB_COLORS, &bm->data, NULL, 0);
|
|
|
|
} else {
|
|
|
|
tDIBHeader header;
|
|
|
|
header.bmi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
header.bmi.biWidth = nw;
|
|
|
|
header.bmi.biHeight = -sf->h; // Always a top down bitmap!!
|
|
|
|
header.bmi.biPlanes = 1;
|
|
|
|
header.bmi.biBitCount = sf->bpp;
|
|
|
|
header.bmi.biCompression = BI_BITFIELDS;
|
|
|
|
header.bmi.biSizeImage = 0;
|
|
|
|
header.bmi.biXPelsPerMeter = 0;
|
|
|
|
header.bmi.biYPelsPerMeter = 0;
|
|
|
|
header.bmi.biClrUsed = 0;
|
|
|
|
header.bmi.biClrImportant = 0;
|
|
|
|
|
|
|
|
// setup RGB bit masks
|
|
|
|
if (sf->bpp == BPP_16) {
|
|
|
|
header.red_mask = 0x7c00;
|
|
|
|
header.green_mask = 0x03e0;
|
|
|
|
header.blue_mask = 0x001f;
|
|
|
|
bm->rowsize = nw * 2;
|
|
|
|
} else if (sf->bpp == BPP_32 || sf->bpp == BPP_24) {
|
|
|
|
header.red_mask = 0x00ff0000;
|
|
|
|
header.green_mask = 0x0000ff00;
|
|
|
|
header.blue_mask = 0x000000ff;
|
|
|
|
bm->rowsize = nw * 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
bm->hbm = CreateDIBSection(GDI_DATA(hOffscreenDC), (BITMAPINFO *)&header, DIB_RGB_COLORS, &bm->data, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bm->hbm) {
|
|
|
|
ddgr_PushError("CreateDIBSection failed.");
|
|
|
|
delete bm;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bm->hwnd = NULL; // This is set by application
|
|
|
|
|
|
|
|
sf->obj = (void *)bm;
|
|
|
|
|
|
|
|
return true;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// destroys the DIB allocated from create
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void ddgr_gdi_surf_Destroy(ddgr_surface *sf) {
|
|
|
|
tGDISurface *bm = (tGDISurface *)sf->obj;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
ASSERT(bm->hbm);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
DeleteObject(bm->hbm);
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
delete bm;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clears a GDI surface.
|
2024-04-16 18:56:40 +00:00
|
|
|
void ddgr_gdi_surf_Clear(ddgr_surface *dsf, ddgr_color col, int l, int t, int w, int h) {
|
|
|
|
HBITMAP old_bmp;
|
|
|
|
HBRUSH clr_brush, old_brush;
|
|
|
|
HDC hdc;
|
|
|
|
tGDISurface *dbm = (tGDISurface *)dsf->obj;
|
|
|
|
int red, green, blue;
|
|
|
|
ddgr_color color = col;
|
|
|
|
|
|
|
|
switch (dsf->bpp) {
|
|
|
|
case BPP_16:
|
|
|
|
red = GR_COLOR_RED(color);
|
|
|
|
green = GR_COLOR_GREEN(color);
|
|
|
|
blue = GR_COLOR_BLUE(color);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BPP_32:
|
|
|
|
case BPP_24:
|
|
|
|
red = (color & 0x00ff0000) >> 16;
|
|
|
|
green = (color & 0x0000ff00) >> 8;
|
|
|
|
blue = (color & 0x000000ff);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Int3(); // BAD
|
|
|
|
}
|
|
|
|
|
|
|
|
clr_brush = CreateSolidBrush(RGB((BYTE)red, (BYTE)green, (BYTE)blue));
|
|
|
|
|
|
|
|
// Are we clearing the primary display?
|
|
|
|
if (dbm->hbm == NULL) {
|
|
|
|
if (dbm->hwnd)
|
|
|
|
hdc = GetDC(dbm->hwnd);
|
|
|
|
else
|
|
|
|
hdc = GetDC(GDI_DATA(hPrimaryWnd));
|
|
|
|
} else {
|
|
|
|
hdc = GDI_DATA(hOffscreenDC);
|
|
|
|
old_bmp = (HBITMAP)SelectObject(hdc, dbm->hbm);
|
|
|
|
}
|
|
|
|
old_brush = (HBRUSH)SelectObject(hdc, clr_brush);
|
|
|
|
|
|
|
|
Rectangle(hdc, l, t, l + w, t + h);
|
|
|
|
|
|
|
|
SelectObject(hdc, old_brush);
|
|
|
|
|
|
|
|
if (dbm->hbm == NULL) {
|
|
|
|
// do if clearing was done on primary display.
|
|
|
|
if (dbm->hwnd)
|
|
|
|
ReleaseDC(dbm->hwnd, hdc);
|
|
|
|
else
|
|
|
|
ReleaseDC(GDI_DATA(hPrimaryWnd), hdc);
|
|
|
|
} else {
|
|
|
|
SelectObject(hdc, old_bmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteObject(clr_brush);
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// blts one GDI bitmap to another. Ability to blt directly to the screen is also
|
|
|
|
// supported.
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_surf_Blt(ddgr_surface *dsf, int dx, int dy, ddgr_surface *ssf, int sx, int sy, int sw, int sh) {
|
|
|
|
HBITMAP old_bmp;
|
|
|
|
HBITMAP old_bmp2;
|
|
|
|
HDC hdc_dest;
|
|
|
|
tGDISurface *dbm = (tGDISurface *)dsf->obj;
|
|
|
|
tGDISurface *sbm = (tGDISurface *)ssf->obj;
|
|
|
|
|
|
|
|
// note that if our destination bitmap is the 'screen', then we use the GDI hwnd DC
|
|
|
|
// else we use the DC of the window specified in the destination.
|
|
|
|
if (dbm->hbm == NULL) {
|
|
|
|
if (dbm->hwnd == NULL)
|
|
|
|
hdc_dest = GetDC(GDI_DATA(hPrimaryWnd));
|
|
|
|
else
|
|
|
|
hdc_dest = GetDC(dbm->hwnd);
|
|
|
|
} else {
|
|
|
|
hdc_dest = CreateCompatibleDC(NULL);
|
|
|
|
old_bmp2 = (HBITMAP)SelectObject(hdc_dest, dbm->hbm);
|
|
|
|
}
|
|
|
|
|
|
|
|
old_bmp = (HBITMAP)SelectObject(GDI_DATA(hOffscreenDC), sbm->hbm);
|
|
|
|
|
|
|
|
BOOL bltres = BitBlt(hdc_dest, dx, dy, sw, sh, GDI_DATA(hOffscreenDC), sx, sy, SRCCOPY);
|
|
|
|
|
|
|
|
SelectObject(GDI_DATA(hOffscreenDC), old_bmp);
|
|
|
|
|
|
|
|
if (dbm->hbm == NULL) {
|
|
|
|
if (dbm->hwnd == NULL)
|
|
|
|
ReleaseDC(GDI_DATA(hPrimaryWnd), hdc_dest);
|
|
|
|
else
|
|
|
|
ReleaseDC(dbm->hwnd, hdc_dest);
|
|
|
|
} else {
|
|
|
|
SelectObject(hdc_dest, old_bmp2);
|
|
|
|
DeleteDC(hdc_dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (bltres) ? true : false;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// simply extracts the data and rowsize from the DDGR object in 'sf'
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_surf_Lock(ddgr_surface *sf, void **ptr, int *rowsize) {
|
|
|
|
tGDISurface *bm = (tGDISurface *)sf->obj;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
*ptr = bm->data;
|
|
|
|
*rowsize = bm->rowsize;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
return true;
|
2024-04-16 03:43:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// invalidates the data and rowsize in 'sf'
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
bool ddgr_gdi_surf_Unlock(ddgr_surface *sf, void *ptr) { return true; }
|
2024-04-16 03:43:29 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// attaches a window handle to this surface. useful in clearing and blting to
|
|
|
|
// screens.
|
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
void ddgr_gdi_surf_AttachHandle(ddgr_surface *sf, unsigned handle) {
|
|
|
|
tGDISurface *gbm = (tGDISurface *)sf->obj;
|
2024-04-16 03:43:29 +00:00
|
|
|
|
2024-04-16 18:56:40 +00:00
|
|
|
gbm->hwnd = (HWND)handle;
|
|
|
|
}
|