Colors messed up on ATI cards

Started by
11 comments, last by Melo 24 years, 5 months ago
You must use the GetPixelFormat() function of DDraw. I'm not sure how it works exactly, because I have never used it, so just look in ddraw.doc for it. You should always use this function, because you never know what kind of format the pixels will be in 16bpp.

Good luck

Advertisement
I have an ATI Rage II+; the color format is 5-5-5. Best thing to do is use GetPixelFormat to check so your code will work on anything.
One of my machines have an ATI Xpert (128 chipset), and the format is 565.

Jim

to beat a dead horse....

for maximum compatibility, be SURE to check either the pixel format or the surface description(which also contains the pixel format) of your surfaces.

most(not all) ATI cards use 555 in 16 bit mode.

also, there are some cards out there that store their pixels as BGR instead of RGB, and thus, checking the pixel format is paramount.

Get off my lawn!

BGR yuck! Why do hardware guys make it so tough. I have a 565 RGB card and have been able to test using some bit-shifting for speedy conversion, and it works great my problem is testing on every graphic card could get rough. I also have some general functions that use all of the pixel format for a slower but always accurate picture. Since I don't want to test for every possible combination and most cards are 565 RGB I am going to test for 16 bits with 6 green bits and if that is the case use my bit-shift routine otherwise I will use the slower general routine.

Does anybody have a better approach or good bit-shift macros for 555 and BGR?

------------------
Glen Martin
Dynamic Adventures Inc.
http://www.dynamicadventures.com

Glen Martin
Dynamic Adventures Inc.
Zenfar
just have a set of functions for every pixel format (RGB 555, RGB 565, BGR 555, BGR 565) and when you check the card's pixel format, set a function pointer to the right function.

Your code will be a bit bigger, but thats the price you pay for good compatibility.

Note that i'm not saying to call a function every time you want to work with a pixel. Use macros (or inline functions) inside more general functions, and have function pointers pointing to these more general functions (4 diff functions, 4 times the code, but you can just copy/paste).

Also note that this is a solution off the top of my head, because I havent really dived into supporting all 16bit formats yet.. right now I just support RGB 565 which my card uses..

I use this macro from LaMothe's Tricks of the Windows Game Programming Gurus for RGB 565 mode...

#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 6) + ((r & 31) << 11))

It is much faster than the other code I was using. But I tried is 555 macro on an ATI card and it didn't work. Could have been a non-RGB mode.

------------------
Glen Martin
Dynamic Adventures Inc.
http://www.dynamicadventures.com

Glen Martin
Dynamic Adventures Inc.
Zenfar
D3DXCreateTextureFromFile() or D3DXCreateTextureFromMemory() will automatically do any color conversion you need.

I usually don't use these functions because they do not allow as much control over texture creation (opaque, static, dynamic flags, etc.)

I usually handle this problem like this: I store all textures on disk in a known format (usually 32-bit or 24-bit RGB, or DXT compressed) I then have quick, optimized routines for common 16-bit formats (565, 555 RGB, haven't seen BGR, but it could happen), a simple copy when source format matches the hardware's format (32-bit textures, or support for DXTn compression,) and a slower, generic, "everything else," fallback.

GetPixelFormat is your best bet.

Structures and globals for holding the RGB info
// Container structure for RGB masks
typedef struct _RGBMASK
{
ULONG rgbRed;
ULONG rgbGreen;
ULONG rgbBlue;
} RGBMASK;

// Container structure for (5,6,5 or 5,5,5 and masking)
typedef struct _RGB16
{
RGBQUAD depth;
RGBQUAD amount;
RGBQUAD position;
RGBMASK mask;
} RGB16;

RGB16 rgb16;

extern int RedMask, GreenMask, BlueMask; // RGB Masks
RedPos, GreenPos, BluePos; // RGB Positions

Macros that will make a RGB pixel wheter the card is 555 or 565 or any other excentric format.

#define RED(p) (p >> RedPos) // Extracts Red color
#define GREEN(p) ((p & GreenMask) >> GreenPos) // Extracts Green color
#define BLUE(p) (p & BlueMask) // Extracts Blue color
#define RGB16(r, g, b) ((r << RedPos) | (g << GreenPos) | b) // Creates RGB pixel

void DDGetPixelFormat()
{
DDSURFACEDESC2 ddsd; // DirectDraw Surface Description
BYTE shiftcount; // Shift Counter

// Get a surface despriction.
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_PIXELFORMAT;
FrontSurf->Surface->GetSurfaceDesc(&ddsd);
// Fill in the masking values for extracting colors.
rgb16.mask.rgbRed = ddsd.ddpfPixelFormat.dwRBitMask;
rgb16.mask.rgbGreen = ddsd.ddpfPixelFormat.dwGBitMask;
rgb16.mask.rgbBlue = ddsd.ddpfPixelFormat.dwBBitMask;

// Get red surface information.
shiftcount = 0;
while(!(ddsd.ddpfPixelFormat.dwRBitMask & 1))
{
ddsd.ddpfPixelFormat.dwRBitMask >>= 1;
shiftcount++;
}
rgb16.depth.rgbRed = (BYTE)ddsd.ddpfPixelFormat.dwRBitMask;
rgb16.position.rgbRed = shiftcount;
rgb16.amount.rgbRed = (ddsd.ddpfPixelFormat.dwRBitMask == 0x1f) ? 3 : 2;

// Get green surface information.
shiftcount = 0;
while(!(ddsd.ddpfPixelFormat.dwGBitMask & 1))
{
ddsd.ddpfPixelFormat.dwGBitMask >>= 1;
shiftcount++;
}
rgb16.depth.rgbGreen =(BYTE)ddsd.ddpfPixelFormat.dwGBitMask;
rgb16.position.rgbGreen = shiftcount;
rgb16.amount.rgbGreen = (ddsd.ddpfPixelFormat.dwGBitMask == 0x1f) ? 3 : 2;

// Get Blue surface information.
shiftcount = 0;
while(!(ddsd.ddpfPixelFormat.dwBBitMask & 1))
{
ddsd.ddpfPixelFormat.dwBBitMask >>= 1;
shiftcount++;
}
rgb16.depth.rgbBlue =(BYTE)ddsd.ddpfPixelFormat.dwBBitMask;
rgb16.position.rgbBlue = shiftcount;
rgb16.amount.rgbBlue = (ddsd.ddpfPixelFormat.dwBBitMask == 0x1f) ? 3 : 2;
// Fill in variables so we dont' have to access the structure anymore.
RedMask = rgb16.mask.rgbRed; // Red Mask
GreenMask = rgb16.mask.rgbGreen; // Green Mask
BlueMask = rgb16.mask.rgbBlue; // Blue Mask
RedPos = rgb16.position.rgbRed; // Red Position
GreenPos = rgb16.position.rgbGreen; // Green Position
BluePos = rgb16.position.rgbBlue; // Blue Position
}

Sorry if it all messy. E-mail me and I wil send it to you properley.

Hardcore Until The End.
Thanx alot folks
But I'm asking myself: Why does no function come with DirectDraw that does this job?

WORD IDirectDraw::GetPixelValue (BYTE red, BYTE green, BYTE blue)

Bye

This topic is closed to new replies.

Advertisement