1345 lines
36 KiB
C
1345 lines
36 KiB
C
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <mmsystem.h> // for timeGetTime()
|
|
#include "drawdibi.h"
|
|
#include "profdisp.h"
|
|
|
|
//#include "msvideo.h"
|
|
//#include "lockbm.h"
|
|
//#include "setdi.h"
|
|
|
|
// Remove inline assembly warning
|
|
#pragma warning(disable:4704)
|
|
|
|
//
|
|
// Set+Blt must be N% faster in order to say a driver isn't good
|
|
//
|
|
#define PROFDISP_FUDGE 110
|
|
|
|
#ifndef WIN32
|
|
#define GdiFlush()
|
|
#endif
|
|
|
|
DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi);
|
|
static UINT NEAR PASCAL ProfDispCanDrawDib(LPBITMAPINFOHEADER lpbi);
|
|
|
|
static HPALETTE CreateTestPalette(BOOL);
|
|
|
|
#ifndef WIN32
|
|
|
|
//C6 will die if we dont redefine this.
|
|
#undef GlobalFreePtr
|
|
#define GlobalFreePtr(p) GlobalFree(GlobalPtrHandle(p))
|
|
|
|
#pragma alloc_text(DRAWDIB, DrawDibProfileDisplay)
|
|
#pragma alloc_text(DRAWDIB, ProfDispCanDrawDib)
|
|
#endif
|
|
|
|
#ifndef QUERYDIBSUPPORT
|
|
#define QUERYDIBSUPPORT 3073
|
|
#endif
|
|
|
|
#ifndef QDI_SETDIBITS
|
|
#define QDI_SETDIBITS 0x0001
|
|
#define QDI_GETDIBITS 0x0002
|
|
#define QDI_DIBTOSCREEN 0x0004
|
|
#define QDI_STRETCHDIB 0x0008
|
|
#endif
|
|
|
|
/*
|
|
** ProfDisp - profile the display driver
|
|
*/
|
|
|
|
#define BITMAP_X 320
|
|
#define BITMAP_Y 240
|
|
#define N_FRAMES 10
|
|
#define STRETCH_N 190 // 1.90 times
|
|
|
|
#ifdef DEBUG
|
|
#define FIRST_N 0 // do four bit
|
|
#else
|
|
#define FIRST_N 1
|
|
#endif
|
|
|
|
#define BITBLTINDEX 5
|
|
#define BACKINDEX 6
|
|
|
|
// Internal return codes from DrawDibTest
|
|
|
|
#define CANT_DO_THESE_BITS 1
|
|
#define CANT_DO_STRETCHDIBITS 2
|
|
#define STRETCHDI_FASTER 3
|
|
#define OTHER_FASTER 4
|
|
|
|
static HWND ghwnd ;
|
|
|
|
#ifndef WIN32
|
|
#define CODE _based(_segname("_CODE"))
|
|
#define STACK _based(_segname("_STACK"))
|
|
#else
|
|
#define CODE
|
|
#define STACK
|
|
#endif
|
|
|
|
static UINT ProfileDisplay(HDC hdc, UINT wBitsToTest, int dx, int dy) ;
|
|
static BOOL IsDisplay16Bit(HDC hdc ) ;
|
|
static BOOL IsDisplay32Bit(HDC hdc ) ;
|
|
static UINT DrawDibTest(HDC hdc, LPBITMAPINFOHEADER FAR *alpbi, UINT wFrames,UINT wStretch ) ;
|
|
static void FreeFrames( LPBITMAPINFOHEADER FAR *alpbi) ;
|
|
static void MakeFrames(LPBITMAPINFOHEADER FAR *alpbi, UINT bits, UINT wXSize,UINT wYSize ) ;
|
|
static HANDLE MakeDib( HBITMAP hbitmap, UINT bits ) ;
|
|
|
|
static TCHAR CODE szBoot[] = TEXT("boot" );
|
|
static TCHAR CODE szDisplay[] = TEXT("display.drv" );
|
|
static TCHAR CODE szNull[] = TEXT("") ;
|
|
static TCHAR CODE szDrawdib[] = TEXT("drawdib" );
|
|
static TCHAR CODE szSystemIni[] = TEXT("system.ini") ;
|
|
static TCHAR CODE szNxNxNxType[] = TEXT(" %dx%dx%d(%s%u)");
|
|
static TCHAR CODE szEntryFormat[] = TEXT("%d,%d,%d,%d");
|
|
static TCHAR CODE szU[] = TEXT("%u");
|
|
static TCHAR CODE sz02U[] = TEXT("%02u");
|
|
static TCHAR CODE sz565[] = TEXT("565 ");
|
|
static TCHAR CODE sz555[] = TEXT("555 ");
|
|
static TCHAR CODE szRGB[] = TEXT("RGB ");
|
|
static TCHAR CODE szBGR[] = TEXT("BGR ");
|
|
|
|
// The following two strings are loaded from MSVIDEO.DLL - defined in
|
|
// video\video.rc. If they cannot be found there, use these definitions
|
|
static TCHAR CODE szProfilingDefault[] = TEXT("Profiling Display");
|
|
static TCHAR CODE szListbox[] = TEXT("ListBox");
|
|
|
|
#if 0 // dont warn any-more
|
|
#ifndef WIN32
|
|
static TCHAR CODE szWarning[] = TEXT("Warning!");
|
|
|
|
static TCHAR CODE szDisplaySucks[]=
|
|
TEXT("You may encounter display performance problems; ")
|
|
TEXT("please contact the manufacturer of your video ")
|
|
TEXT("board to see if an updated driver is available.");
|
|
#endif
|
|
#endif
|
|
|
|
#define ARRAYLEN(array) (sizeof(array)/sizeof(array[0]))
|
|
|
|
static int result[5] = {
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1};
|
|
|
|
//
|
|
// UINT displayFPS[7][3][2] [test dib][stretch][method]
|
|
//
|
|
// this array contains fps numbers times 10, ie 10 == 1fps
|
|
// zero means the test was not run.
|
|
//
|
|
// testdib:
|
|
// 0 = 4bpp DIB (debug only)
|
|
// 1 = 8bpp DIB
|
|
// 2 = 16bpp DIB
|
|
// 3 = 24bpp DIB
|
|
// 4 = 32bpp DIB
|
|
// 5 = BitBlt
|
|
// 6 = 8bpp DIB (with non identity palette)
|
|
//
|
|
// stretch:
|
|
// 0 = 1:1
|
|
// 1 = 1:2
|
|
// 2 = 1:N (realy 2:3)
|
|
//
|
|
// method (for stretch == 1:1)
|
|
// 0 = StretchDIBits()
|
|
// 1 = SetDIBits() + BitBlt *
|
|
//
|
|
// method (for stretch != 1:1)
|
|
// 0 = StretchDIBits()
|
|
// 1 = StretchDIB() + StretchDIBits() **
|
|
//
|
|
// method (for testdib == 5, bitblt)
|
|
// 0 = BitBlt foreground palette
|
|
// 1 = BitBlt background palette
|
|
//
|
|
// NOTE high color dibs (> 8) are not tested on devices with bitdepths <= 8
|
|
//
|
|
// NOTE stretching tests are not run unless the device does stretching.
|
|
// (RasterCaps has RC_STRETCHBLT or RC_STRETCHDIBITS set)
|
|
//
|
|
// * NOTE if we can access bitmaps, we dont use SetDIBits() we use direct
|
|
// code.
|
|
//
|
|
// ** NOTE (StretchDIB is not a GDI api...)
|
|
//
|
|
// EXAMPLE:
|
|
// displayFPS[1][0][0] is the FPS of 1:1 StretchDIBits() on a 8bpp DIB
|
|
// displayFPS[1][0][1] is the FPS of Set+BitBlt() on a 8bpp DIB
|
|
// displayFPS[1][1][0] is the FPS of 1:2 StretchDIBits() on a 8bpp DIB
|
|
//
|
|
// how the ResultN flags get set:
|
|
//
|
|
// PD_CAN_DRAW_DIB (can draw this dib 1:1 using some method...)
|
|
// displayFPS[N][0][0] != 0 or displayFPS[N][0][1] != 0
|
|
//
|
|
// PD_CAN_STRETCHDIB (can stretch this dib using StretchDIBits)
|
|
// displayFPS[N][1][0] > displayFPS[N][1][1] or
|
|
// displayFPS[N][2][0] > displayFPS[N][2][1]
|
|
//
|
|
// PD_STRETCHDIB_1_1_OK (StretchDIBits faster than Set+BitBlt)
|
|
// displayFPS[N][0][0] > displayFPS[N][0][1]
|
|
//
|
|
// PD_STRETCHDIB_1_2_OK (StretchDIBits 1:2 is faster the doing it our self)
|
|
// displayFPS[N][1][0] > displayFPS[N][1][1]
|
|
//
|
|
// PD_STRETCHDIB_1_N_OK (StretchDIBits 1:N is faster the doing it our self)
|
|
// displayFPS[N][2][0] > displayFPS[N][2][1]
|
|
//
|
|
|
|
static UINT displayFPS[7] // 0=4bbp, 1=8bpp, 2=16bpp, 3=24bpp, 4=32bit, 5=BitBlt, 6=Dib ~1:1
|
|
[3] // 0=1:1, 1=1:2, 2=1:N
|
|
[2]; // 0=DrawDib, 1=Set+Blt (or ~1:1 for BitBlt)
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @api LONG | atoi | local version of atoi
|
|
*
|
|
***************************************************************************/
|
|
|
|
static int NEAR PASCAL atoi(char FAR *sz)
|
|
{
|
|
int i = 0;
|
|
|
|
while (*sz && *sz >= '0' && *sz <= '9')
|
|
i = i*10 + *sz++ - '0';
|
|
|
|
return i;
|
|
}
|
|
|
|
static void FAR InitProfDisp(BOOL fForceMe)
|
|
{
|
|
TCHAR ach[80];
|
|
TCHAR achDisplay[80];
|
|
HDC hdc;
|
|
int i;
|
|
int n;
|
|
int BitDepth;
|
|
|
|
GetPrivateProfileString(szBoot, szDisplay, szNull,
|
|
achDisplay, ARRAYLEN(achDisplay), szSystemIni);
|
|
|
|
hdc = GetDC(NULL);
|
|
|
|
BitDepth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
|
|
|
|
n = GetBitmapType();
|
|
|
|
switch(n & BM_TYPE)
|
|
{
|
|
default:
|
|
case BM_8BIT: ach[0] = 0; break;
|
|
case BM_16555: lstrcpy(ach, sz555); break;
|
|
case BM_16565: lstrcpy(ach, sz565); break;
|
|
case BM_24BGR:
|
|
case BM_32BGR: lstrcpy(ach, szBGR); break;
|
|
case BM_24RGB:
|
|
case BM_32RGB: lstrcpy(ach, szRGB); break;
|
|
}
|
|
|
|
wsprintf(achDisplay + lstrlen(achDisplay), szNxNxNxType,
|
|
GetSystemMetrics(SM_CXSCREEN),
|
|
GetSystemMetrics(SM_CYSCREEN),
|
|
BitDepth,(LPSTR)ach, n >> 4);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
GetProfileString(szDrawdib, achDisplay, szNull, ach, ARRAYLEN(ach));
|
|
|
|
for (i=0,n=1; n<5; n++)
|
|
{
|
|
if (ach[i] == '\0')
|
|
{
|
|
result[n] = -1;
|
|
}
|
|
else
|
|
{
|
|
result[n] = atoi(ach+i);
|
|
while (ach[i] != 0 && ach[i] != ',')
|
|
i++;
|
|
if (ach[i] != 0)
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if (fForceMe ||
|
|
result[1] == -1 ||
|
|
result[2] == -1 ||
|
|
result[3] == -1 ||
|
|
result[4] == -1)
|
|
{
|
|
TestDibFormats(BITMAP_X,BITMAP_Y);
|
|
|
|
wsprintf(ach, szEntryFormat,
|
|
result[1], result[2], result[3], result[4]);
|
|
WriteProfileString(szDrawdib, achDisplay, ach);
|
|
|
|
#if 0
|
|
//
|
|
// if the DISPLAY driver isn't very good at drawing DIBs then warn the user.
|
|
//
|
|
// we will only warn if the device is at least 8bpp
|
|
//
|
|
if (BitDepth >= 8 && !(result[1] & PD_STRETCHDIB_1_1_OK))
|
|
{
|
|
#ifndef WIN32
|
|
MessageBox(NULL, szDisplaySucks, szWarning,
|
|
#ifdef BIDI
|
|
MB_RTL_READING |
|
|
#endif
|
|
|
|
MB_OK | MB_SYSTEMMODAL | MB_ICONEXCLAMATION);
|
|
#else
|
|
RPF(("Display driver probably too slow for AVI"));
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
*
|
|
*****************************************************************/
|
|
|
|
static UINT NEAR PASCAL ProfDispCanDrawDib(LPBITMAPINFOHEADER lpbi)
|
|
{
|
|
int n;
|
|
LONG l;
|
|
HDC hdc;
|
|
UINT w;
|
|
|
|
if (result[1] == -1 || lpbi==NULL)
|
|
InitProfDisp(FALSE);
|
|
|
|
if (lpbi == NULL)
|
|
return 0;
|
|
|
|
switch (lpbi->biCompression)
|
|
{
|
|
//
|
|
// standard format use our pre-computed performance numbers.
|
|
//
|
|
case BI_RGB:
|
|
n = (int)lpbi->biBitCount / 8;
|
|
return result[n];
|
|
|
|
case BI_RLE4:
|
|
case BI_RLE8:
|
|
//
|
|
// return the un-rle results *but* RLE can't stretch
|
|
//
|
|
return result[1] & PD_CAN_DRAW_DIB|PD_STRETCHDIB_1_1_OK;
|
|
|
|
//
|
|
// custom format, ask the DISPLAY driver
|
|
//
|
|
default:
|
|
l = 0;
|
|
w = 0;
|
|
|
|
hdc = GetDC(NULL);
|
|
|
|
if (Escape(hdc, QUERYDIBSUPPORT, (int)lpbi->biSize, (LPVOID)lpbi, (LPVOID)&l) > 0)
|
|
{
|
|
// make sure the driver realy realy gave us back flags.
|
|
if (l & ~(0x00FF))
|
|
l = 0;
|
|
|
|
if (l & QDI_DIBTOSCREEN)
|
|
w |= PD_STRETCHDIB_1_1_OK | PD_CAN_DRAW_DIB;
|
|
|
|
if (l & QDI_STRETCHDIB)
|
|
w |= PD_CAN_STRETCHDIB;
|
|
|
|
/* what about stretching? fast? */
|
|
}
|
|
|
|
ReleaseDC(NULL, hdc);
|
|
return w;
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
* @doc EXTERNAL DrawDib
|
|
*
|
|
* @api void | DrawDibProfileDisplay | Profiles the display for DrawDib.
|
|
*
|
|
* @parm LPBITMAPINFOHEADER | parms | Specifies bitmap information.
|
|
* Set to null if no information is available.
|
|
*
|
|
*****************************************************************/
|
|
|
|
DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi)
|
|
{
|
|
if (lpbi == NULL)
|
|
{
|
|
InitProfDisp(TRUE) ;
|
|
return (DWORD)(LPVOID)displayFPS;
|
|
}
|
|
else
|
|
return ProfDispCanDrawDib(lpbi);
|
|
}
|
|
|
|
LPVOID FAR TestDibFormats(int dx, int dy)
|
|
{
|
|
int dxScreen,dyScreen;
|
|
RECT rc;
|
|
HWND hwnd;
|
|
HDC hdc;
|
|
int n;
|
|
int i;
|
|
HCURSOR hcur;
|
|
HPALETTE hpal;
|
|
#ifdef DEBUG
|
|
HPALETTE hpalT;
|
|
#endif
|
|
HWND hwndActive;
|
|
TCHAR szProfiling[80];
|
|
|
|
// dont change this without changing MSVIDEO.RC
|
|
#define IDS_PROFILING 4000
|
|
|
|
extern HMODULE ghInst; // in MSVIDEO\init.c
|
|
|
|
if (!LoadString(ghInst, IDS_PROFILING, szProfiling, sizeof(szProfiling)/sizeof(TCHAR)))
|
|
lstrcpy(szProfiling, szProfilingDefault);
|
|
|
|
#ifdef WIN32
|
|
#define GetCurrentInstance() GetModuleHandle(NULL)
|
|
#else
|
|
#define GetCurrentInstance() NULL
|
|
#endif
|
|
|
|
dxScreen = GetSystemMetrics(SM_CXSCREEN);
|
|
dyScreen = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
// fill in displayFPS[7][3][2];
|
|
|
|
for (n=0; n<7; n++)
|
|
for (i=0; i<3; i++)
|
|
displayFPS[n][i][0] =
|
|
displayFPS[n][i][1] = 0;
|
|
|
|
SetRect(&rc, 0, 0, dx, dy);
|
|
AdjustWindowRect(&rc, (WS_OVERLAPPED | WS_CAPTION | WS_BORDER), FALSE);
|
|
OffsetRect(&rc, -rc.left, -rc.top);
|
|
|
|
hwnd =
|
|
#ifdef BIDI
|
|
CreateWindowEx(WS_EX_BIDI_SCROLL | WS_EX_BIDI_MENU |WS_EX_BIDI_NOICON,
|
|
szListbox, // Class name
|
|
szProfiling, // Caption
|
|
LBS_NOINTEGRALHEIGHT|
|
|
(WS_OVERLAPPED | WS_CAPTION | WS_BORDER),
|
|
(dxScreen - rc.right) / 2,
|
|
(dyScreen - rc.bottom) / 2,
|
|
rc.right,
|
|
rc.bottom,
|
|
(HWND)NULL, // Parent window (no parent)
|
|
(HMENU)NULL, // use class menu
|
|
GetCurrentInstance(), // handle to window instance
|
|
(LPTSTR)NULL // no params to pass on
|
|
);
|
|
|
|
#else
|
|
CreateWindow (
|
|
szListbox, // Class name
|
|
szProfiling, // Caption
|
|
LBS_NOINTEGRALHEIGHT|
|
|
(WS_OVERLAPPED | WS_CAPTION | WS_BORDER),
|
|
(dxScreen - rc.right) / 2,
|
|
(dyScreen - rc.bottom) / 2,
|
|
rc.right,
|
|
rc.bottom,
|
|
(HWND)NULL, // Parent window (no parent)
|
|
(HMENU)NULL, // use class menu
|
|
GetCurrentInstance(), // handle to window instance
|
|
(LPTSTR)NULL // no params to pass on
|
|
);
|
|
#endif
|
|
|
|
// make the window top most
|
|
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
|
SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
|
|
|
|
// and show it.
|
|
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
|
SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
|
|
|
|
// and activate it.
|
|
hwndActive = GetActiveWindow();
|
|
SetActiveWindow(hwnd);
|
|
|
|
hdc = GetDC(hwnd);
|
|
hcur = SetCursor(NULL);
|
|
|
|
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
|
|
{
|
|
hpal = CreateTestPalette(TRUE);
|
|
SelectPalette(hdc, hpal, FALSE);
|
|
RealizePalette(hdc);
|
|
}
|
|
|
|
Yield();
|
|
Yield();
|
|
Yield();
|
|
|
|
#ifndef WIN32
|
|
//
|
|
// make sure no junk is around in the SmartDrv cache, this will
|
|
// mess with the timings
|
|
//
|
|
_asm {
|
|
mov ax,4A10h ; tell Bambi to flush the cache
|
|
mov bx,0001h
|
|
int 2fh
|
|
|
|
mov ah,0Dh ; tell other people to commit...
|
|
int 21h
|
|
}
|
|
#else
|
|
GdiFlush();
|
|
#endif
|
|
|
|
for (n=FIRST_N; n<5; n++)
|
|
result[n] = ProfileDisplay(hdc, n==0 ? 4 : n*8, dx, dy);
|
|
|
|
#ifdef DEBUG
|
|
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
|
|
{
|
|
//
|
|
// re-run the 8bit tests with a background palette
|
|
//
|
|
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
|
|
RealizePalette(hdc);
|
|
|
|
hpalT = CreateTestPalette(FALSE);
|
|
SelectPalette(hdc, hpalT, TRUE);
|
|
RealizePalette(hdc);
|
|
|
|
Yield();
|
|
Yield();
|
|
Yield();
|
|
|
|
ProfileDisplay(hdc, 8, dx, dy);
|
|
|
|
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
|
|
RealizePalette(hdc);
|
|
DeleteObject(hpalT);
|
|
DeleteObject(hpal);
|
|
}
|
|
#endif
|
|
|
|
SetCursor(hcur);
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
if (hwndActive)
|
|
SetActiveWindow(hwndActive);
|
|
|
|
DestroyWindow(hwnd) ;
|
|
|
|
return (LPVOID)displayFPS;
|
|
}
|
|
|
|
static UINT ProfileDisplay(HDC hdc, UINT wBitsToTest, int dx, int dy)
|
|
{
|
|
LPBITMAPINFOHEADER alpbi[N_FRAMES];
|
|
UINT wRetval;
|
|
|
|
if (GetDeviceCaps(hdc, BITSPIXEL) *
|
|
GetDeviceCaps(hdc, PLANES) <= 8 && wBitsToTest > 8)
|
|
return 0;
|
|
|
|
alpbi[0] = NULL;
|
|
|
|
MakeFrames(alpbi,wBitsToTest,dx,dy);
|
|
|
|
wRetval = 0 ;
|
|
|
|
if (!alpbi[0])
|
|
return (UINT)-1 ;
|
|
|
|
switch(DrawDibTest(hdc,alpbi,N_FRAMES,100))
|
|
{
|
|
case CANT_DO_THESE_BITS:
|
|
goto done ;
|
|
|
|
case CANT_DO_STRETCHDIBITS:
|
|
wRetval = PD_CAN_DRAW_DIB ;
|
|
goto done ;
|
|
|
|
case STRETCHDI_FASTER:
|
|
wRetval = PD_STRETCHDIB_1_1_OK ;
|
|
/* Falling through */
|
|
|
|
case OTHER_FASTER:
|
|
wRetval |= PD_CAN_DRAW_DIB;
|
|
}
|
|
|
|
if (DrawDibTest(hdc,alpbi,N_FRAMES,STRETCH_N) == STRETCHDI_FASTER)
|
|
wRetval |= PD_STRETCHDIB_1_N_OK|PD_CAN_STRETCHDIB;
|
|
|
|
if (DrawDibTest(hdc,alpbi,N_FRAMES,200) == STRETCHDI_FASTER)
|
|
wRetval |= PD_STRETCHDIB_1_2_OK|PD_CAN_STRETCHDIB;
|
|
|
|
done:
|
|
FreeFrames(alpbi);
|
|
|
|
return wRetval;
|
|
}
|
|
|
|
static UINT DrawDibTest(HDC hdc,LPBITMAPINFOHEADER FAR *alpbi,UINT wFrames,UINT wStretch)
|
|
{
|
|
HDC hdcMem ;
|
|
HBITMAP hbitmap ;
|
|
HBITMAP hbitmapOld ;
|
|
|
|
UINT wBits ;
|
|
DWORD dwSize;
|
|
DWORD wSizeColors ;
|
|
DWORD dwSizeImage;
|
|
|
|
volatile LPBITMAPINFOHEADER lpbi ;
|
|
LPBYTE bits ;
|
|
LPBITMAPINFOHEADER lpbiStretch ;
|
|
LPBYTE bitsStretch ;
|
|
DWORD time0 = 0;
|
|
DWORD time1 = 0;
|
|
DWORD time2 = 0;
|
|
RECT rc ;
|
|
int XDest,YDest,cXDest,cYDest ;
|
|
int cXSrc,cYSrc ;
|
|
int i ;
|
|
int n ;
|
|
int q ;
|
|
UINT DibUsage;
|
|
HPALETTE hpal;
|
|
BOOL fBack;
|
|
BOOL f;
|
|
|
|
lpbi = alpbi[0];
|
|
|
|
/*
|
|
** Get stuff common to all frames
|
|
*/
|
|
wBits = lpbi->biBitCount ;
|
|
//cXSrc = (int)lpbi->biWidth ;
|
|
//cYSrc = (int)lpbi->biHeight ;
|
|
//cXDest = wStretch*(int)lpbi->biWidth/100 ;
|
|
//cYDest = wStretch*(int)lpbi->biHeight/100 ;
|
|
|
|
cXSrc = 100*(int)lpbi->biWidth/wStretch ;
|
|
cYSrc = 100*(int)lpbi->biHeight/wStretch ;
|
|
cXDest = (int)lpbi->biWidth ;
|
|
cYDest = (int)lpbi->biHeight ;
|
|
|
|
// are we background'ed
|
|
n = wStretch == 100 ? 0 : wStretch == 200 ? 1 : 2;
|
|
fBack = wBits==8 && displayFPS[1][n][0] != 0;
|
|
|
|
if (lpbi->biBitCount <= 8)
|
|
wSizeColors = sizeof(RGBQUAD) * (int)(lpbi->biClrUsed ? lpbi->biClrUsed : (1 << (int)lpbi->biBitCount));
|
|
else
|
|
wSizeColors = 0 ;
|
|
|
|
bits = (LPBYTE)lpbi + (int)lpbi->biSize + wSizeColors ;
|
|
|
|
if (GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES) <= 8 && wBits > 8)
|
|
return CANT_DO_STRETCHDIBITS;
|
|
|
|
////if (wStretch != 100 && !(GetDeviceCaps(hdc,RASTERCAPS)&(RC_STRETCHDIB|RC_STRETCHBLT)))
|
|
|
|
if (wStretch != 100 && !(GetDeviceCaps(hdc,RASTERCAPS)&(RC_STRETCHDIB)))
|
|
return CANT_DO_STRETCHDIBITS ;
|
|
|
|
if (wStretch != 100 && wBits == 4)
|
|
return CANT_DO_STRETCHDIBITS ;
|
|
|
|
if (wStretch != 100 && (GetWinFlags() & WF_CPU286))
|
|
return STRETCHDI_FASTER;
|
|
|
|
// if (wStretch != 100 && wBits > 8) //!!!
|
|
// wFrames = 4;
|
|
|
|
lpbi->biWidth = cXSrc;
|
|
lpbi->biHeight = cYSrc;
|
|
|
|
// get current palette
|
|
hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
|
|
SelectPalette(hdc, hpal, fBack);
|
|
RealizePalette(hdc);
|
|
|
|
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
|
|
{
|
|
DibUsage = DIB_PAL_COLORS;
|
|
}
|
|
else
|
|
{
|
|
DibUsage = DIB_RGB_COLORS;
|
|
}
|
|
|
|
////GetClientRect(hwnd,&rc) ;
|
|
GetClipBox(hdc,&rc) ;
|
|
XDest = (rc.right - cXDest)/2 ;
|
|
YDest = (rc.bottom - cYDest)/2 ;
|
|
|
|
time0 = 0;
|
|
|
|
if (wBits == 16 && !IsDisplay16Bit(hdc))
|
|
goto test_bitmap;
|
|
|
|
if (wBits == 32 && !IsDisplay32Bit(hdc))
|
|
goto test_bitmap;
|
|
|
|
time0 = timeGetTime() ;
|
|
|
|
for (i=0; i<(int)wFrames; i++)
|
|
{
|
|
lpbi = alpbi[i%N_FRAMES];
|
|
bits = ((LPBYTE)lpbi) + (int)lpbi->biSize + wSizeColors ;
|
|
|
|
#ifdef WIN32
|
|
/*
|
|
* to correctly model the behaviour of DrawDibDraw, we
|
|
* use SetDIBitsToDevice if 1:1 (source rect == dest rect).
|
|
*/
|
|
if ( (cXSrc == cXDest) && (cYSrc == cYDest)) {
|
|
f = SetDIBitsToDevice(hdc, XDest, YDest, cXDest, cYDest,
|
|
0, 0, 0, cYSrc,
|
|
bits, (LPBITMAPINFO)lpbi, DibUsage);
|
|
} else
|
|
#endif
|
|
{
|
|
f = StretchDIBits(
|
|
hdc,
|
|
XDest,YDest,cXDest,cYDest,
|
|
0,0,cXSrc, cYSrc,
|
|
bits,(LPBITMAPINFO)lpbi,DibUsage,SRCCOPY) ;
|
|
}
|
|
}
|
|
|
|
GdiFlush();
|
|
|
|
time0 = timeGetTime() - time0 ;
|
|
|
|
if (f == 0)
|
|
time0 = 0;
|
|
|
|
test_bitmap:
|
|
time1 = 0;
|
|
|
|
if (wStretch == 100)
|
|
{
|
|
PSETDI psd;
|
|
|
|
psd = (PSETDI)LocalAlloc(LPTR, sizeof(SETDI));
|
|
|
|
if (psd == NULL)
|
|
goto done;
|
|
|
|
hbitmap = CreateCompatibleBitmap(hdc,cXDest,cYDest) ;
|
|
hdcMem = CreateCompatibleDC(NULL) ;
|
|
hbitmapOld = SelectObject(hdcMem,hbitmap) ;
|
|
|
|
f = SetBitmapBegin(
|
|
psd, // structure
|
|
hdc, // device
|
|
hbitmap, // bitmap to set into
|
|
lpbi, // --> BITMAPINFO of source
|
|
DibUsage);
|
|
|
|
psd->hdc = hdc;
|
|
|
|
if (f)
|
|
f = SetBitmap(psd, 0, 0, cXDest, cYDest, bits, 0, 0, cXDest, cYDest);
|
|
|
|
if (f)
|
|
{
|
|
// SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
|
|
// RealizePalette(hdc);
|
|
|
|
time1 = timeGetTime();
|
|
|
|
for (i=0; i<(int)wFrames; i++)
|
|
{
|
|
SetBitmap(psd, 0, 0, cXDest, cYDest, bits, 0, 0, cXDest, cYDest);
|
|
BitBlt(hdc,XDest,YDest,cXDest,cYDest,hdcMem,0,0,SRCCOPY);
|
|
}
|
|
|
|
GdiFlush();
|
|
|
|
time1 = timeGetTime() - time1 ;
|
|
|
|
SetBitmapEnd(psd);
|
|
|
|
// SelectPalette(hdc, hpal, fBack);
|
|
// RealizePalette(hdc);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if ((int)lpbi->biBitCount == GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES))
|
|
{
|
|
time2 = timeGetTime() ;
|
|
|
|
for (i=0; i<(int)wFrames; i++)
|
|
BitBlt(hdc,XDest,YDest,cXDest,cYDest,hdcMem,0,0,SRCCOPY) ;
|
|
|
|
GdiFlush();
|
|
|
|
time2 = timeGetTime() - time2 ;
|
|
}
|
|
#endif
|
|
|
|
LocalFree((HLOCAL)psd);
|
|
SelectObject(hdcMem,hbitmapOld) ;
|
|
DeleteObject(hbitmap) ;
|
|
DeleteDC(hdcMem) ;
|
|
}
|
|
else
|
|
{
|
|
if (wBits == 16 && !IsDisplay16Bit(hdc))
|
|
goto done;
|
|
|
|
if (wBits == 32 && !IsDisplay32Bit(hdc))
|
|
goto done;
|
|
|
|
#ifdef NOSTRETCH
|
|
/*
|
|
* StretchDIB not ported from ASM yet - so StretchDIBits must win.
|
|
*/
|
|
time1 = time0 + 1;
|
|
#else
|
|
// Calc size we need to allocate for stretched bits
|
|
|
|
dwSizeImage = (DWORD)(UINT)cYDest*(DWORD)(((UINT)cXDest*(UINT)lpbi->biBitCount+31)/32*4);
|
|
dwSize = (int)lpbi->biSize + (int)lpbi->biClrUsed*sizeof(RGBQUAD);
|
|
|
|
if ((lpbiStretch = (LPVOID)GlobalAllocPtr(GHND,dwSize + dwSizeImage)) != NULL)
|
|
{
|
|
hmemcpy(lpbiStretch, lpbi, dwSize);
|
|
lpbiStretch->biWidth = cXDest;
|
|
lpbiStretch->biHeight = cYDest;
|
|
lpbiStretch->biSizeImage = dwSizeImage;
|
|
bitsStretch = (LPBYTE)lpbiStretch + (UINT)dwSize;
|
|
|
|
time1 = timeGetTime() ;
|
|
|
|
for (i=0; i<(int)wFrames; i++)
|
|
{
|
|
lpbi = alpbi[i%N_FRAMES];
|
|
bits = ((LPBYTE)lpbi) + (int)lpbi->biSize + wSizeColors;
|
|
|
|
StretchDIB(
|
|
lpbiStretch,bitsStretch,
|
|
0,0,cXDest,cYDest,
|
|
lpbi,bits,
|
|
0,0,cXSrc,cYSrc);
|
|
#ifdef WIN32
|
|
/*
|
|
* to correctly model the behaviour of DrawDibDraw, we
|
|
* use SetDIBitsToDevice if 1:1 (source rect == dest rect).
|
|
*/
|
|
f = SetDIBitsToDevice(hdc, XDest, YDest, cXDest, cYDest,
|
|
0, 0, 0, cYSrc,
|
|
bits, (LPBITMAPINFO)lpbi, DibUsage);
|
|
#else
|
|
f = StretchDIBits(
|
|
hdc,
|
|
XDest,YDest,cXDest,cYDest,
|
|
0,0,cXDest,cYDest,
|
|
bitsStretch,(LPBITMAPINFO)lpbiStretch,DibUsage,SRCCOPY);
|
|
#endif
|
|
}
|
|
|
|
GdiFlush();
|
|
|
|
time1 = timeGetTime() - time1 ;
|
|
|
|
GlobalFreePtr(lpbiStretch);
|
|
|
|
if (f == 0)
|
|
time1 = 0;
|
|
#endif
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if ((int)lpbi->biBitCount == GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES))
|
|
{
|
|
hbitmap = CreateCompatibleBitmap(hdc,cXSrc,cYSrc) ;
|
|
hdcMem = CreateCompatibleDC(NULL) ;
|
|
hbitmapOld = SelectObject(hdcMem,hbitmap) ;
|
|
lpbi = alpbi[0];
|
|
bits = ((LPBYTE)lpbi) + (int)lpbi->biSize + wSizeColors;
|
|
SetDIBits(hdc,hbitmap,0,cYSrc,bits,(LPBITMAPINFO)lpbi,DibUsage);
|
|
|
|
SelectPalette(hdcMem, hpal, FALSE);
|
|
// RealizePalette(hdcMem);
|
|
|
|
time2 = timeGetTime() ;
|
|
|
|
for (i=0; i<(int)wFrames; i++)
|
|
StretchBlt(hdc,XDest,YDest,cXDest,cYDest,hdcMem,0,0,cXSrc,cYSrc,SRCCOPY) ;
|
|
|
|
GdiFlush();
|
|
|
|
time2 = timeGetTime() - time2 ;
|
|
|
|
SelectObject(hdcMem,hbitmapOld) ;
|
|
DeleteObject(hbitmap) ;
|
|
DeleteDC(hdcMem) ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
done:
|
|
/* time0 is the time required to do StretchDIBits */
|
|
/* time1 is the time required to do Set + BitBlt */
|
|
/* time2 is the time required to do a BitBlt */
|
|
|
|
//
|
|
// compute the FPS * 10 and store for later use.
|
|
//
|
|
n = wStretch == 100 ? 0 : wStretch == 200 ? 1 : 2;
|
|
q = fBack ? BACKINDEX : wBits/8;
|
|
|
|
time1 = (DWORD)MulDiv((int)time1,PROFDISP_FUDGE,100);
|
|
|
|
displayFPS[q][n][0] = time0 ? (UINT)MulDiv(wFrames,10000,(int)time0) : 0;
|
|
displayFPS[q][n][1] = time1 ? (UINT)MulDiv(wFrames,10000,(int)time1) : 0;
|
|
|
|
if (time2)
|
|
displayFPS[BITBLTINDEX][n][fBack] = (UINT)MulDiv(wFrames,10000,(int)time2);
|
|
|
|
RPF(("DrawDibTest %dx%dx%d %d StretchDIBits=%04lu SetDI+BitBlt=%04lu BitBlt=%04lu %ls",cXDest,cYDest,wBits,wStretch,time0,time1,time2,(LPSTR)(time0 < time1 ? TEXT("") : TEXT("SUCKS!"))));
|
|
|
|
lpbi->biWidth = cXDest;
|
|
lpbi->biHeight = cYDest;
|
|
|
|
if (time0 == 0)
|
|
{
|
|
return time1 ? OTHER_FASTER : CANT_DO_THESE_BITS;
|
|
}
|
|
else
|
|
{
|
|
if (time1)
|
|
return (time0 < time1) ? STRETCHDI_FASTER : OTHER_FASTER;
|
|
else
|
|
return STRETCHDI_FASTER;
|
|
}
|
|
}
|
|
|
|
static void MakeFrames(LPBITMAPINFOHEADER FAR *alpbi, UINT bits, UINT wXSize,UINT wYSize )
|
|
{
|
|
int i ;
|
|
int x ;
|
|
int y ;
|
|
LPBITMAPINFOHEADER lpbi ;
|
|
DWORD dwSizeImage;
|
|
BYTE _huge *pb;
|
|
WORD FAR *pw;
|
|
DWORD FAR *pdw;
|
|
UINT rc;
|
|
HDC hdc;
|
|
|
|
hdc = GetDC(NULL);
|
|
rc = GetDeviceCaps(hdc, RASTERCAPS);
|
|
ReleaseDC(NULL,hdc);
|
|
|
|
FreeFrames(alpbi);
|
|
|
|
dwSizeImage = wYSize*(DWORD)((wXSize*bits/8+3)&~3);
|
|
|
|
lpbi = (LPVOID)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
|
|
lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
|
|
lpbi->biWidth = wXSize ;
|
|
lpbi->biHeight = wYSize ;
|
|
lpbi->biPlanes = 1 ;
|
|
lpbi->biBitCount = bits ;
|
|
lpbi->biCompression = BI_RGB ;
|
|
lpbi->biSizeImage = dwSizeImage;
|
|
lpbi->biXPelsPerMeter = 0 ;
|
|
lpbi->biYPelsPerMeter = 0 ;
|
|
lpbi->biClrUsed = 0 ;
|
|
lpbi->biClrImportant = 0 ;
|
|
|
|
// !!! These should be RGB DIBs if the device isn't a palette device!
|
|
|
|
if (bits == 4)
|
|
{
|
|
lpbi->biClrUsed = 16;
|
|
}
|
|
else if (bits == 8)
|
|
{
|
|
lpbi->biClrUsed = 256;
|
|
}
|
|
|
|
pb = (BYTE _huge *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD);
|
|
|
|
if (bits == 4)
|
|
{
|
|
for (y=0; y<(int)wYSize; y++)
|
|
for (x=0; x<(int)wXSize; x += 2)
|
|
{
|
|
i = ((x / (wXSize / 4)) + 4 * (y / (wYSize / 4)));
|
|
i += i * 16;
|
|
*pb++ = i;
|
|
}
|
|
|
|
if (rc & RC_PALETTE)
|
|
{
|
|
pw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
|
|
|
|
for (i=0; i<8; i++)
|
|
*pw++ = i;
|
|
|
|
for (i=0; i<8; i++)
|
|
*pw++ = 248+i;
|
|
}
|
|
else
|
|
{
|
|
pdw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
|
|
|
|
*pdw++ = 0x00000000; // 0000 black
|
|
*pdw++ = 0x00800000; // 0001 dark red
|
|
*pdw++ = 0x00008000; // 0010 dark green
|
|
*pdw++ = 0x00808000; // 0011 mustard
|
|
*pdw++ = 0x00000080; // 0100 dark blue
|
|
*pdw++ = 0x00800080; // 0101 purple
|
|
*pdw++ = 0x00008080; // 0110 dark turquoise
|
|
*pdw++ = 0x00C0C0C0; // 1000 gray
|
|
*pdw++ = 0x00808080; // 0111 dark gray
|
|
*pdw++ = 0x00FF0000; // 1001 red
|
|
*pdw++ = 0x0000FF00; // 1010 green
|
|
*pdw++ = 0x00FFFF00; // 1011 yellow
|
|
*pdw++ = 0x000000FF; // 1100 blue
|
|
*pdw++ = 0x00FF00FF; // 1101 pink (magenta)
|
|
*pdw++ = 0x0000FFFF; // 1110 cyan
|
|
*pdw++ = 0x00FFFFFF; // 1111 white
|
|
}
|
|
}
|
|
else if (bits == 8)
|
|
{
|
|
for (y=0; y<(int)wYSize; y++)
|
|
for (x=0; x<(int)wXSize; x++)
|
|
{
|
|
*pb++ = 10 + y * 236 / (int)wYSize;
|
|
}
|
|
|
|
if (rc & RC_PALETTE)
|
|
{
|
|
pw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
|
|
|
|
for (i=0; i<256; i++)
|
|
*pw++ = i;
|
|
}
|
|
else
|
|
{
|
|
pdw = (LPVOID)((LPBYTE)lpbi+(int)lpbi->biSize);
|
|
|
|
for (i=0; i<256; i++)
|
|
*pdw++ = RGB(i,0,0);
|
|
}
|
|
}
|
|
else if (bits == 16)
|
|
{
|
|
for (y=0; y<(int)wYSize; y++)
|
|
for (x=0; x<(int)wXSize; x++)
|
|
{
|
|
*pb++ = (BYTE) ((UINT)y * 32u / wYSize);
|
|
*pb++ = (BYTE)(((UINT)x * 32u / wXSize) << 2);
|
|
}
|
|
}
|
|
else if (bits == 24)
|
|
{
|
|
for (y=0; y<(int)wYSize; y++)
|
|
for (x=0; x<(int)wXSize; x++)
|
|
{
|
|
*pb++ = (BYTE) (y * 256l / wYSize);
|
|
*pb++ = (BYTE)~(x * 256l / wXSize);
|
|
*pb++ = (BYTE) (x * 256l / wXSize);
|
|
}
|
|
}
|
|
else if (bits == 32)
|
|
{
|
|
for (y=0; y<(int)wYSize; y++)
|
|
for (x=0; x<(int)wXSize; x++)
|
|
{
|
|
*pb++ = (BYTE)~(x * 256l / wXSize);
|
|
*pb++ = (BYTE) (y * 256l / wYSize);
|
|
*pb++ = (BYTE) (x * 256l / wXSize);
|
|
*pb++ = 0;
|
|
}
|
|
}
|
|
|
|
for ( i=0; i<N_FRAMES; i++ )
|
|
alpbi[i] = lpbi;
|
|
}
|
|
|
|
static void FreeFrames(LPBITMAPINFOHEADER FAR *alpbi)
|
|
{
|
|
UINT w ;
|
|
|
|
if (!alpbi[0])
|
|
return ;
|
|
|
|
for (w=0; w<N_FRAMES; w++)
|
|
if (alpbi[w] && (w == 0 || alpbi[w] != alpbi[w-1]))
|
|
GlobalFreePtr(alpbi[w]);
|
|
|
|
for (w=0; w<N_FRAMES; w++)
|
|
alpbi[w] = NULL;
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
* CreateTestPalette()
|
|
*
|
|
*/
|
|
static HPALETTE CreateTestPalette(BOOL f)
|
|
{
|
|
HDC hdc;
|
|
int i;
|
|
|
|
struct {
|
|
WORD palVersion;
|
|
WORD palNumEntries;
|
|
PALETTEENTRY palPalEntry[256];
|
|
} pal;
|
|
|
|
pal.palNumEntries = 256;
|
|
pal.palVersion = 0x0300;
|
|
|
|
hdc = GetDC(NULL);
|
|
GetSystemPaletteEntries(hdc, 0, 256, &pal.palPalEntry[0]);
|
|
ReleaseDC(NULL,hdc);
|
|
|
|
for (i = 10; i < 246; i++)
|
|
pal.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
|
|
|
|
if (!f)
|
|
pal.palPalEntry[0].peRed = 255;
|
|
|
|
return CreatePalette((LPLOGPALETTE)&pal);
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
* CreateTestPalette()
|
|
*
|
|
*/
|
|
static HPALETTE CreateTestPalette(BOOL fUp)
|
|
{
|
|
int i;
|
|
HDC hdc;
|
|
|
|
struct {
|
|
WORD palVersion;
|
|
WORD palNumEntries;
|
|
PALETTEENTRY palPalEntry[256];
|
|
} pal;
|
|
|
|
pal.palNumEntries = 256;
|
|
pal.palVersion = 0x0300;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
pal.palPalEntry[i].peRed = 0;
|
|
pal.palPalEntry[i].peGreen = 0;
|
|
pal.palPalEntry[i].peBlue = (BYTE)(fUp ? i : 255 - i);
|
|
pal.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
|
|
}
|
|
|
|
hdc = GetDC(NULL);
|
|
GetSystemPaletteEntries(hdc, 0, 10, &pal.palPalEntry[0]);
|
|
GetSystemPaletteEntries(hdc, 246, 10, &pal.palPalEntry[246]);
|
|
ReleaseDC(NULL,hdc);
|
|
|
|
return CreatePalette((LPLOGPALETTE)&pal);
|
|
}
|
|
#endif
|
|
|
|
#define RGB555_RED 0x7C00
|
|
#define RGB555_GREEN 0x03E0
|
|
#define RGB555_BLUE 0x001F
|
|
|
|
static BOOL IsDisplay16Bit( HDC hdc )
|
|
{
|
|
struct {
|
|
BITMAPINFOHEADER bi;
|
|
RGBQUAD rgbq[256];
|
|
} dib;
|
|
int w ;
|
|
LONG l=0;
|
|
WORD bits[2];
|
|
COLORREF cref ;
|
|
|
|
w = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES) ;
|
|
|
|
if ( w < 15 )
|
|
return FALSE;
|
|
|
|
/*
|
|
** OK, the hardware is at least 16 bits - now test to see
|
|
** if they impelement 5-5-5 RGB
|
|
*/
|
|
|
|
dib.bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
dib.bi.biWidth = 1;
|
|
dib.bi.biHeight = 1;
|
|
dib.bi.biPlanes = 1;
|
|
dib.bi.biBitCount = 16;
|
|
dib.bi.biCompression = BI_RGB;
|
|
dib.bi.biSizeImage = 4;
|
|
dib.bi.biXPelsPerMeter = 0;
|
|
dib.bi.biYPelsPerMeter = 0;
|
|
dib.bi.biClrUsed = 1;
|
|
dib.bi.biClrImportant = 0;
|
|
|
|
//
|
|
// just in case they try to decode it as rle
|
|
//
|
|
bits[0] = 0x0000; // this is RLE EOL
|
|
bits[1] = 0x0100; // this is RLE EOF
|
|
|
|
//
|
|
// send the Escape to see if they support 16bpp DIBs
|
|
//
|
|
if (Escape(hdc, QUERYDIBSUPPORT, (int)dib.bi.biSize, (LPVOID)&dib, (LPVOID)&l) > 0)
|
|
{
|
|
// make sure the driver realy realy gave us back flags.
|
|
if (l & ~(0x00FF))
|
|
l = 0;
|
|
|
|
if (l & (QDI_DIBTOSCREEN|QDI_STRETCHDIB))
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// they dont support the QUERYDIBSUPPORT Escape, try to draw DIBs and see
|
|
// what they do!
|
|
//
|
|
|
|
if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
|
|
return FALSE;
|
|
|
|
cref = GetPixel(hdc,0,0) ;
|
|
|
|
if (cref != RGB(0,0,0))
|
|
return FALSE;
|
|
|
|
/*
|
|
** Display a red pixel of the max value and get it back with
|
|
** GetPixel(). Verify that red has the max value in the RGB
|
|
** triplet and green and blue are nothing.
|
|
*/
|
|
bits[0] = RGB555_RED ;
|
|
if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
|
|
return FALSE;
|
|
|
|
cref = GetPixel(hdc,0,0) & 0x00F8F8F8;
|
|
|
|
if (cref != RGB(0xF8,0,0))
|
|
return FALSE;
|
|
|
|
/*
|
|
** Ditto green. Note that if the driver is implementing 5-6-5, then
|
|
** green will read back as less than full scale and we will catch
|
|
** it here.
|
|
*/
|
|
bits[0] = RGB555_GREEN ;
|
|
if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
|
|
return FALSE;
|
|
|
|
cref = GetPixel(hdc,0,0) & 0x00F8F8F8;
|
|
|
|
if (cref != RGB(0,0xF8,0))
|
|
return FALSE;
|
|
|
|
/*
|
|
** Ditto blue.
|
|
*/
|
|
bits[0] = RGB555_BLUE ;
|
|
if ( !StretchDIBits(hdc,0,0,1,1,0,0,1,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
|
|
return FALSE;
|
|
|
|
cref = GetPixel(hdc,0,0) & 0x00F8F8F8;
|
|
|
|
if (cref != RGB(0,0,0xF8))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL IsDisplay32Bit( HDC hdc )
|
|
{
|
|
struct {
|
|
BITMAPINFOHEADER bi;
|
|
RGBQUAD rgbq[256];
|
|
} dib;
|
|
int w ;
|
|
LONG l=0;
|
|
DWORD bits[2];
|
|
|
|
w = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES) ;
|
|
|
|
if ( w < 15 )
|
|
return FALSE;
|
|
|
|
/*
|
|
** OK, the hardware is at least 16 bits - now test to see
|
|
** if they impelement a 32 bit DIB
|
|
*/
|
|
|
|
dib.bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
dib.bi.biWidth = 2;
|
|
dib.bi.biHeight = 1;
|
|
dib.bi.biPlanes = 1;
|
|
dib.bi.biBitCount = 32;
|
|
dib.bi.biCompression = BI_RGB;
|
|
dib.bi.biSizeImage = 4;
|
|
dib.bi.biXPelsPerMeter = 0;
|
|
dib.bi.biYPelsPerMeter = 0;
|
|
dib.bi.biClrUsed = 1;
|
|
dib.bi.biClrImportant = 0;
|
|
|
|
//
|
|
// send the Escape to see if they support 32bpp DIBs
|
|
//
|
|
if (Escape(hdc, QUERYDIBSUPPORT, (int)dib.bi.biSize, (LPVOID)&dib, (LPVOID)&l) > 0)
|
|
{
|
|
// make sure the driver realy realy gave us back flags.
|
|
if (l & ~(0x00FF))
|
|
l = 0;
|
|
|
|
if (l & (QDI_DIBTOSCREEN|QDI_STRETCHDIB))
|
|
return TRUE;
|
|
}
|
|
|
|
bits[0] = 0x00000000;
|
|
bits[1] = 0x00FFFFFF;
|
|
|
|
//
|
|
// they dont support the QUERYDIBSUPPORT Escape, try to draw DIBs and see
|
|
// what they do!
|
|
//
|
|
if (!StretchDIBits(hdc,0,0,2,1,0,0,2,1,bits,(LPBITMAPINFO)&dib,DIB_RGB_COLORS,SRCCOPY))
|
|
return FALSE;
|
|
|
|
if (GetPixel(hdc,0,0) != 0)
|
|
return FALSE;
|
|
|
|
if ((GetPixel(hdc,1,0) & 0x00F8F8F8) != 0x00F8F8F8)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|