#include "..\ref_soft\r_local.h"
#include "rw_win.h"
#ifndef _WIN32
#error You should not be trying to compile this file on this platform
#endif
static bool s_systemcolors_saved;
static HGDIOBJ previously_selected_GDI_obj;
static int s_syspalindices[] = {COLOR_ACTIVEBORDER, COLOR_ACTIVECAPTION, COLOR_APPWORKSPACE, COLOR_BACKGROUND,
COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNTEXT, COLOR_CAPTIONTEXT,
COLOR_GRAYTEXT, COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT, COLOR_INACTIVEBORDER,
COLOR_INACTIVECAPTION, COLOR_MENU, COLOR_MENUTEXT, COLOR_SCROLLBAR,
COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWTEXT};
#define NUM_SYS_COLORS (sizeof(s_syspalindices) / sizeof(int))
static int s_oldsyscolors[NUM_SYS_COLORS];
typedef struct dibinfo {
BITMAPINFOHEADER header;
RGBQUAD acolors[256];
} dibinfo_t;
typedef struct {
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palEntries[256];
} identitypalette_t;
static identitypalette_t s_ipal;
static void DIB_SaveSystemColors(void);
static void DIB_RestoreSystemColors(void);
bool DIB_Init(unsigned char **ppbuffer, int *ppitch) {
dibinfo_t dibheader;
BITMAPINFO *pbmiDIB = (BITMAPINFO *)&dibheader;
int i;
memset(&dibheader, 0, sizeof(dibheader));
if(!sww_state.hDC) {
if((sww_state.hDC = GetDC(sww_state.hWnd)) == NULL)
return false;
}
if(GetDeviceCaps(sww_state.hDC, RASTERCAPS) & RC_PALETTE) {
sww_state.palettized = true;
if(!s_systemcolors_saved) {
DIB_SaveSystemColors();
s_systemcolors_saved = true;
}
} else {
sww_state.palettized = false;
}
pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmiDIB->bmiHeader.biWidth = vid.width;
pbmiDIB->bmiHeader.biHeight = vid.height;
pbmiDIB->bmiHeader.biPlanes = 1;
pbmiDIB->bmiHeader.biBitCount = 8;
pbmiDIB->bmiHeader.biCompression = BI_RGB;
pbmiDIB->bmiHeader.biSizeImage = 0;
pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
pbmiDIB->bmiHeader.biClrUsed = 256;
pbmiDIB->bmiHeader.biClrImportant = 256;
for(i = 0; i < 256; i++) {
dibheader.acolors[i].rgbRed = (d_8to24table[i] >> 0) & 0xff;
dibheader.acolors[i].rgbGreen = (d_8to24table[i] >> 8) & 0xff;
dibheader.acolors[i].rgbBlue = (d_8to24table[i] >> 16) & 0xff;
}
sww_state.hDIBSection = CreateDIBSection(sww_state.hDC, pbmiDIB, DIB_RGB_COLORS, &sww_state.pDIBBase, NULL, 0);
if(sww_state.hDIBSection == NULL) {
ri.Con_Printf(PRINT_ALL, "DIB_Init() - CreateDIBSection failed\n");
goto fail;
}
if(pbmiDIB->bmiHeader.biHeight > 0) {
*ppbuffer = sww_state.pDIBBase + (vid.height - 1) * vid.width;
*ppitch = -vid.width;
} else {
*ppbuffer = sww_state.pDIBBase;
*ppitch = vid.width;
}
memset(sww_state.pDIBBase, 0xff, vid.width * vid.height);
if((sww_state.hdcDIBSection = CreateCompatibleDC(sww_state.hDC)) == NULL) {
ri.Con_Printf(PRINT_ALL, "DIB_Init() - CreateCompatibleDC failed\n");
goto fail;
}
if((previously_selected_GDI_obj = SelectObject(sww_state.hdcDIBSection, sww_state.hDIBSection)) == NULL) {
ri.Con_Printf(PRINT_ALL, "DIB_Init() - SelectObject failed\n");
goto fail;
}
return true;
fail:
DIB_Shutdown();
return false;
}
void DIB_SetPalette(const unsigned char *_pal) {
const unsigned char *pal = _pal;
LOGPALETTE *pLogPal = (LOGPALETTE *)&s_ipal;
RGBQUAD colors[256];
int i;
int ret;
HDC hDC = sww_state.hDC;
if(sww_state.hdcDIBSection) {
for(i = 0; i < 256; i++, pal += 4) {
colors[i].rgbRed = pal[0];
colors[i].rgbGreen = pal[1];
colors[i].rgbBlue = pal[2];
colors[i].rgbReserved = 0;
}
colors[0].rgbRed = 0;
colors[0].rgbGreen = 0;
colors[0].rgbBlue = 0;
colors[255].rgbRed = 0xff;
colors[255].rgbGreen = 0xff;
colors[255].rgbBlue = 0xff;
if(SetDIBColorTable(sww_state.hdcDIBSection, 0, 256, colors) == 0) {
ri.Con_Printf(PRINT_ALL, "DIB_SetPalette() - SetDIBColorTable failed\n");
}
}
if(sww_state.palettized) {
int i;
HPALETTE hpalOld;
if(SetSystemPaletteUse(hDC, SYSPAL_NOSTATIC) == SYSPAL_ERROR) {
ri.Sys_Error(ERR_FATAL, "DIB_SetPalette() - SetSystemPaletteUse() failed\n");
}
if(sww_state.hPal) {
DeleteObject(sww_state.hPal);
sww_state.hPal = 0;
}
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = 256;
for(i = 0, pal = _pal; i < 256; i++, pal += 4) {
pLogPal->palPalEntry[i].peRed = pal[0];
pLogPal->palPalEntry[i].peGreen = pal[1];
pLogPal->palPalEntry[i].peBlue = pal[2];
pLogPal->palPalEntry[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE;
}
pLogPal->palPalEntry[0].peRed = 0;
pLogPal->palPalEntry[0].peGreen = 0;
pLogPal->palPalEntry[0].peBlue = 0;
pLogPal->palPalEntry[0].peFlags = 0;
pLogPal->palPalEntry[255].peRed = 0xff;
pLogPal->palPalEntry[255].peGreen = 0xff;
pLogPal->palPalEntry[255].peBlue = 0xff;
pLogPal->palPalEntry[255].peFlags = 0;
if((sww_state.hPal = CreatePalette(pLogPal)) == NULL) {
ri.Sys_Error(ERR_FATAL, "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError());
}
if((hpalOld = SelectPalette(hDC, sww_state.hPal, FALSE)) == NULL) {
ri.Sys_Error(ERR_FATAL, "DIB_SetPalette() - SelectPalette failed(%x)\n", GetLastError());
}
if(sww_state.hpalOld == NULL)
sww_state.hpalOld = hpalOld;
if((ret = RealizePalette(hDC)) != pLogPal->palNumEntries) {
ri.Sys_Error(ERR_FATAL, "DIB_SetPalette() - RealizePalette set %d entries\n", ret);
}
}
}
void DIB_Shutdown(void) {
if(sww_state.palettized && s_systemcolors_saved)
DIB_RestoreSystemColors();
if(sww_state.hPal) {
DeleteObject(sww_state.hPal);
sww_state.hPal = 0;
}
if(sww_state.hpalOld) {
SelectPalette(sww_state.hDC, sww_state.hpalOld, FALSE);
RealizePalette(sww_state.hDC);
sww_state.hpalOld = NULL;
}
if(sww_state.hdcDIBSection) {
SelectObject(sww_state.hdcDIBSection, previously_selected_GDI_obj);
DeleteDC(sww_state.hdcDIBSection);
sww_state.hdcDIBSection = NULL;
}
if(sww_state.hDIBSection) {
DeleteObject(sww_state.hDIBSection);
sww_state.hDIBSection = NULL;
sww_state.pDIBBase = NULL;
}
if(sww_state.hDC) {
ReleaseDC(sww_state.hWnd, sww_state.hDC);
sww_state.hDC = 0;
}
}
static void DIB_RestoreSystemColors(void) {
SetSystemPaletteUse(sww_state.hDC, SYSPAL_STATIC);
SetSysColors(NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors);
}
static void DIB_SaveSystemColors(void) {
int i;
for(i = 0; i < NUM_SYS_COLORS; i++)
s_oldsyscolors[i] = GetSysColor(s_syspalindices[i]);
}