You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
9.7 KiB
354 lines
9.7 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: test.c
|
|
*
|
|
* Created: 09-Dec-1992 10:51:46
|
|
* Author: Kirk Olynyk [kirko]
|
|
*
|
|
* Copyright (c) 1991 Microsoft Corporation
|
|
*
|
|
* Contains the test
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <objbase.h>
|
|
#include <math.h> // sin & cos
|
|
#include <stdio.h>
|
|
#include "wndstuff.h"
|
|
|
|
#include <gdiplus.h>
|
|
|
|
using namespace Gdiplus;
|
|
|
|
enum SurfaceFormat {
|
|
SurfaceFormatUnknown,
|
|
SurfaceFormat565,
|
|
SurfaceFormat555
|
|
};
|
|
|
|
/**************************************************************************\
|
|
* GetSurfaceFormat
|
|
*
|
|
* Returns:
|
|
* Returns the display mode, or
|
|
* SurfaceFormatUnknown if unknown or on error.
|
|
*
|
|
* Only recognizes 555 and 565.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
SurfaceFormat
|
|
GetSurfaceFormat(
|
|
HDC hdc
|
|
)
|
|
{
|
|
HBITMAP hbm;
|
|
SurfaceFormat ret = SurfaceFormatUnknown;
|
|
|
|
BYTE bmi_buf[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
|
|
BITMAPINFO *pbmi = (BITMAPINFO *) bmi_buf;
|
|
|
|
memset(bmi_buf, 0, sizeof(bmi_buf));
|
|
|
|
// Create a dummy bitmap from which we can query color format info
|
|
// about the device surface.
|
|
|
|
if ( (hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL )
|
|
{
|
|
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
// Call first time to fill in BITMAPINFO header.
|
|
|
|
GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
|
|
|
|
// First handle the 'simple' case of indexed formats.
|
|
|
|
if ( (pbmi->bmiHeader.biBitCount == 16)
|
|
&& ( pbmi->bmiHeader.biCompression == BI_BITFIELDS ))
|
|
{
|
|
DWORD redMask = 0;
|
|
DWORD greenMask = 0;
|
|
DWORD blueMask = 0;
|
|
|
|
// Call a second time to get the color masks.
|
|
// It's a GetDIBits Win32 "feature".
|
|
|
|
GetDIBits(
|
|
hdc,
|
|
hbm,
|
|
0,
|
|
pbmi->bmiHeader.biHeight,
|
|
NULL,
|
|
pbmi,
|
|
DIB_RGB_COLORS
|
|
);
|
|
|
|
DWORD* masks = reinterpret_cast<DWORD*>(&pbmi->bmiColors[0]);
|
|
|
|
redMask = masks[0];
|
|
greenMask = masks[1];
|
|
blueMask = masks[2];
|
|
|
|
if ((redMask == 0x0000f800) &&
|
|
(greenMask == 0x000007e0) &&
|
|
(blueMask == 0x0000001f) &&
|
|
(pbmi->bmiHeader.biBitCount == 16))
|
|
{
|
|
ret = SurfaceFormat565;
|
|
}
|
|
if ((redMask == 0x00007c00) &&
|
|
(greenMask == 0x000003e0) &&
|
|
(blueMask == 0x0000001f) &&
|
|
(pbmi->bmiHeader.biBitCount == 16))
|
|
{
|
|
ret = SurfaceFormat555;
|
|
}
|
|
}
|
|
|
|
DeleteObject(hbm);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static HBITMAP CreateMyDIB(HDC hdcin, PVOID *ppvBits) {
|
|
// these combined give BITMAPINFO structure.
|
|
struct {
|
|
BITMAPINFOHEADER bmih;
|
|
RGBQUAD rgbquad16[3];
|
|
} bmi;
|
|
|
|
bmi.bmih.biSize = sizeof(BITMAPINFOHEADER);
|
|
bmi.bmih.biWidth = 8;
|
|
bmi.bmih.biHeight = 8;
|
|
bmi.bmih.biPlanes = 1;
|
|
bmi.bmih.biBitCount = 16;
|
|
bmi.bmih.biCompression = BI_BITFIELDS;
|
|
bmi.bmih.biSizeImage = 0;
|
|
bmi.bmih.biXPelsPerMeter = 0;
|
|
bmi.bmih.biYPelsPerMeter = 0;
|
|
bmi.bmih.biClrUsed = 0; // only used for <= 16bpp
|
|
bmi.bmih.biClrImportant = 0;
|
|
|
|
RGBQUAD rgbQuad16[3] = { { 0, 0xf8, 0, 0 }, { 0xe0, 07, 0, 0 }, { 0x1f, 0, 0, 0 } };
|
|
|
|
memcpy(bmi.rgbquad16, rgbQuad16, sizeof(rgbQuad16));
|
|
|
|
HBITMAP hbitmap;
|
|
|
|
hbitmap = CreateDIBSection(
|
|
hdcin,
|
|
(BITMAPINFO*)&bmi,
|
|
DIB_RGB_COLORS,
|
|
ppvBits,
|
|
NULL,
|
|
0);
|
|
|
|
return hbitmap;
|
|
}
|
|
|
|
static int sysColorNum[4] = {
|
|
COLOR_3DSHADOW,
|
|
COLOR_3DFACE,
|
|
COLOR_3DHIGHLIGHT,
|
|
COLOR_DESKTOP
|
|
};
|
|
|
|
static void DumpBitmap(FILE *fp, WORD *pBits) {
|
|
WORD * pBits2 = pBits;
|
|
|
|
WORD col = *pBits2++;
|
|
int count;
|
|
for (count = 1;count < 64; count++) {
|
|
if (col != *pBits2++) break;
|
|
}
|
|
if (count == 64) {
|
|
fprintf(fp, " Solid %04x\n\n", col);
|
|
} else {
|
|
int i,j;
|
|
for (i=0;i<8;i++) {
|
|
fprintf(fp, " ");
|
|
for (j=0;j<8;j++) {
|
|
fprintf(fp, "%04x ", *pBits++);
|
|
}
|
|
fprintf(fp, "\n");
|
|
}
|
|
fprintf(fp, "\n");
|
|
}
|
|
}
|
|
|
|
static void DumpColor(FILE *fp, Color &c) {
|
|
fprintf(fp, "(%02x, %02x, %02x)", c.GetRed(), c.GetGreen(), c.GetBlue());
|
|
}
|
|
|
|
VOID
|
|
Test(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
HDC hdc = NULL;
|
|
Graphics *g = NULL;
|
|
HBITMAP hbm = NULL;
|
|
HDC hdcOffscreen = NULL;
|
|
HBITMAP bmOld = NULL;
|
|
PVOID pvBits = NULL;
|
|
FILE *fp = NULL;
|
|
SurfaceFormat format = SurfaceFormatUnknown;
|
|
|
|
Rect rect1(
|
|
0,
|
|
40,
|
|
8,
|
|
8
|
|
);
|
|
|
|
Rect rect2(
|
|
0,
|
|
0,
|
|
8,
|
|
8
|
|
);
|
|
|
|
hdc = GetDC(hwnd);
|
|
g = new Graphics(hdc);
|
|
|
|
{
|
|
HDC h = g->GetHDC();
|
|
format = GetSurfaceFormat(h);
|
|
|
|
if ( (format == SurfaceFormat555)
|
|
|| (format == SurfaceFormat565)) {
|
|
|
|
hbm = CreateMyDIB(h, &pvBits);
|
|
hdcOffscreen = CreateCompatibleDC(h);
|
|
bmOld = (HBITMAP) SelectObject(hdcOffscreen, hbm);
|
|
} else {
|
|
printf("Error: Display doesn't seem to be in 16bpp\n");
|
|
g->ReleaseHDC(h);
|
|
goto ErrorOut;
|
|
}
|
|
g->ReleaseHDC(h);
|
|
}
|
|
|
|
fp = fopen("output.txt", "w");
|
|
fprintf(fp,
|
|
"The 16bpp mode on this machine is in %s format.\n\n"
|
|
"This is test output for examining rendering to 16bpp (555/565) destinations,\n"
|
|
"and comparing Win9x with NT output.\n"
|
|
"Related bugs: #294433, #292492, #298264, #298283, #351610, #321960.\n"
|
|
"We use 3*256 test colors; for each channel, one test color for each possible\n"
|
|
"0-255 level.\n"
|
|
"This output has 2 sections.\n\n"
|
|
|
|
"--------------------------------------------------------------------------------\n"
|
|
"SECTION 1: GetNearestColor\n"
|
|
"Shows the result of calling GetNearestColor on that color. For section 2, we\n"
|
|
"also remember which colors were the result of a GetNearestColor call.\n"
|
|
"\n",
|
|
(format == SurfaceFormat555) ? "555" : "565"
|
|
);
|
|
|
|
int num;
|
|
|
|
const int numColors = 256 * 3;
|
|
|
|
BYTE colors[numColors][3];
|
|
BOOL isNearest[numColors];
|
|
|
|
for (num=0; num < numColors; num++) {
|
|
isNearest[num] = FALSE;
|
|
}
|
|
|
|
for (num=0; num < numColors; num++) {
|
|
colors[num][0] = 0;
|
|
colors[num][1] = 0;
|
|
colors[num][2] = 0;
|
|
|
|
int chnum = num / 256;
|
|
|
|
colors[num][chnum] = (BYTE) (num % 256);
|
|
|
|
Color color(colors[num][0], colors[num][1], colors[num][2]);
|
|
Color color2(colors[num][0], colors[num][1], colors[num][2]);
|
|
g->GetNearestColor(&color2);
|
|
|
|
BYTE nc[3];
|
|
nc[0] = color2.GetRed();
|
|
nc[1] = color2.GetGreen();
|
|
nc[2] = color2.GetBlue();
|
|
|
|
int nearestIdx = nc[chnum] + 256*chnum;
|
|
nc[chnum] = 0;
|
|
if ((nc[0] != 0) ||
|
|
(nc[1] != 0) ||
|
|
(nc[2] != 0) ||
|
|
(nearestIdx < 0) ||
|
|
(nearestIdx >= numColors))
|
|
{
|
|
fprintf(fp, "UNEXPECTED: ");
|
|
}
|
|
else
|
|
{
|
|
isNearest[nearestIdx] = TRUE;
|
|
}
|
|
fprintf(fp, "GetNearestColor(");
|
|
DumpColor(fp, color);
|
|
fprintf(fp, ") == ");
|
|
DumpColor(fp, color2);
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
fprintf(fp,
|
|
"\n--------------------------------------------------------------------------------\n"
|
|
"SECTION 2: FillRect\n"
|
|
"Shows the result of calling FillRectangle of an 8x8 rectangle using the input\n"
|
|
"color. If all 64 pixels are the same, we say \"Solid xxxx\" with the resulting\n"
|
|
"16-bit value. Otherwise, all 64 pixels are reported.\n"
|
|
"\n"
|
|
"* next to the color means that GetNearestColor can return this color.\n"
|
|
"\n"
|
|
);
|
|
|
|
for (num=0; num < numColors; num++) {
|
|
Color color(colors[num][0], colors[num][1], colors[num][2]);
|
|
|
|
fprintf(fp, "%sColor: ", isNearest[num]?"* ":" ");
|
|
DumpColor(fp, color);
|
|
fprintf(fp, "\n");
|
|
|
|
SolidBrush solidBrush1(color);
|
|
|
|
fprintf(fp, " GDI+ FillRectangle to screen (uses GDI CreateSolidBrush & PatBlt):\n");
|
|
|
|
{
|
|
g->FillRectangle(&solidBrush1, rect1);
|
|
HDC hdcGraphics = g->GetHDC();
|
|
BitBlt(hdcOffscreen, 0, 0, rect1.Width, rect1.Height, hdcGraphics, rect1.X, rect1.Y, SRCCOPY);
|
|
g->ReleaseHDC(hdcGraphics);
|
|
}
|
|
|
|
DumpBitmap(fp, (WORD *) pvBits);
|
|
|
|
fprintf(fp, " GDI+ FillRectangle to DIBSection (uses GDI+ dithering):\n");
|
|
|
|
{
|
|
Graphics g2(hdcOffscreen);
|
|
g2.FillRectangle(&solidBrush1, rect2);
|
|
}
|
|
|
|
DumpBitmap(fp, (WORD *) pvBits);
|
|
}
|
|
|
|
ErrorOut:
|
|
if (fp) fclose(fp);
|
|
|
|
if (bmOld) SelectObject(hdcOffscreen, bmOld);
|
|
if (hdcOffscreen) DeleteDC(hdcOffscreen);
|
|
if (hbm) DeleteObject(hbm);
|
|
|
|
delete g;
|
|
|
|
if (hdc) ReleaseDC(hwnd, hdc);
|
|
}
|
|
|