Open main menu

Difference between revisions of "API-Truecolor"

423 bytes added ,  07:16, 11 July 2009
Updated the reference to reflect API changes regarding initGraphics
(→‎Complete API function reference: Documented new error values.)
(Updated the reference to reflect API changes regarding initGraphics)
Line 27: Line 27:
'''NOTE''': This API was designed with backwards-compatibility for 8-bit Graphics only engines in mind. If your engine does not make use of per-pixel RGB color graphics, you should not have to change anything, so long as ENABLE_RGB_COLOR is set in configuration during compilation, so that functions link properly.
'''NOTE''': This API was designed with backwards-compatibility for 8-bit Graphics only engines in mind. If your engine does not make use of per-pixel RGB color graphics, you should not have to change anything, so long as ENABLE_RGB_COLOR is set in configuration during compilation, so that functions link properly.


#Determine/obtain desired pixel format
#Init with desired pixel format
#*If your engine can only produce graphics in one RGB color format, initialize a Graphics::PixelFormat to the desired format.
#*If your engine can only produce graphics in one RGB color format, initialize a Graphics::PixelFormat to the desired format, and call initGraphics with a pointer to that format as the fourth parameter.
#**For instance, if your engine can only produce graphics in RGB555, you would say Graphics::PixelFormat(2, 3, 3, 3, 8, 10, 5, 0, 0);
#**For instance, if your engine can only produce graphics in RGB555, you would say Graphics::PixelFormat myFormat(2, 3, 3, 3, 8, 10, 5, 0, 0);
#*If your engine can easily support any RGB mode (for instance if it converts from YUV), call OSystem::getSupportedFormats and use the first value in the returned Common::List.
#*If your engine can easily support any RGB mode (for instance if it converts from YUV), call initGraphics with NULL for the fourth parameter.
#*If your engine can support more than one RGB mode, but not all of them...
#*If your engine can support more than one RGB mode, but not all of them...
#*#Produce a Common::List of Graphics::PixelFormat objects describing the supported formats. This list must be in order of descending preference, so that the most desired format is first, and the least desired is last.
#*#Produce a Common::List of Graphics::PixelFormat objects describing the supported formats. This list must be in order of descending preference, so that the most desired format is first, and the least desired is last.
#*#Use the return value from Graphics::findCompatibleFormat(OSystem::getSupportedFormats(),{your format list}
#*#call initGraphics with this list of formats as the fourth parameter
#Check the return value of OSystem::getScreenFormat() to see if setup of your desired format was successful. If setup was not successful, it will return Graphics::PixelFormat::createFormatCLUT8();
#Check the return value of OSystem::getScreenFormat() to see if setup of your desired format was successful. If setup was not successful, it will return Graphics::PixelFormat::createFormatCLUT8();
#*If the setup was not successful, and your engine cannot run in 256 colors, display an error and return.
#*If the setup was not successful, and your engine cannot run in 256 colors, display an error and return.
Line 42: Line 42:
<syntax type="C++">
<syntax type="C++">
Common::Error QuuxEngine::run() {
Common::Error QuuxEngine::run() {
// Obtain the best possible format from the backend.
Graphics::PixelFormat ourFormat;
Graphics::PixelFormat ourFormat = _system->getSupportedFormats().front();
// Request the backend to initialize a 640 x 480 surface with the best available format.
initGraphics(640, 480, true, NULL);


// If our engine could only handle one format, we would specify it here instead of asking the backend:
// If our engine could only handle one format, we would specify it here instead of asking the backend:
// // RGB555
// // RGB555
// Graphics::PixelFormat ourFormat(2, 3, 3, 3, 8, 10, 5, 0,  0);
// ourFormat(2, 3, 3, 3, 8, 10, 5, 0,  0);
// initGraphics(640, 480, true, &ourFormat);


// If our engine could handle only a few formats, this would look quite different:
// If our engine could handle only a few formats, this would look quite different:
Line 53: Line 55:
//
//
// // RGB555
// // RGB555
// Graphics::PixelFormat ourFormat(2, 3, 3, 3, 8, 10, 5, 0,  0);  
// ourFormat(2, 3, 3, 3, 8, 10, 5, 0,  0);  
// ourFormatList.push_back(ourFormat);
// ourFormatList.push_back(ourFormat);
//
//
Line 60: Line 62:
// ourFormatList.push_back(ourFormat);
// ourFormatList.push_back(ourFormat);
//
//
// // Get the best format which is compatible between our engine and the backend
// // Use the best format which is compatible between our engine and the backend
// ourFormat = Graphics::findCompatibleFormat(_system->getSupportedFormats(),ourFormatList);
// initGraphics(640, 480, true, ourFormatList);


// Attempt to initialize a 640 x 480 surface with that format
// Get the format the system was able to provide
initGraphics(640, 480, true, &ourFormat);
 
// Use the format the system was able to provide
// in case it cannot support that format at our requested resolution
// in case it cannot support that format at our requested resolution
format = _system->getScreenFormat();
ourFormat = _system->getScreenFormat();


byte *offscreenBuffer = (byte *)malloc(640 * 480 * format.bytesPerPixel);
byte *offscreenBuffer = (byte *)malloc(640 * 480 * ourFormat.bytesPerPixel);


if (format.bytesPerPixel == 1) {
if (ourFormat.bytesPerPixel == 1) {
// Initialize palette to simulate RGB332
// Initialize palette to simulate RGB332


Line 101: Line 100:
// The result is equivalent to:
// The result is equivalent to:
// uint32 mask = 0;
// uint32 mask = 0;
// for (int i = format.bytesPerPixel; i > 0; i--) {
// for (int i = ourFormat.bytesPerPixel; i > 0; i--) {
// mask <<= 8;
// mask <<= 8;
// mask |= 0xFF;
// mask |= 0xFF;
// }
// }
uint32 mask = (1 << (format.bytesPerPixel << 3)) - 1;
uint32 mask = (1 << (ourFormat.bytesPerPixel << 3)) - 1;


// Repeat this until the event manager tells us to stop
// Repeat this until the event manager tells us to stop
Line 111: Line 110:


// Keep t from exceeding the number of bits in each pixel.
// Keep t from exceeding the number of bits in each pixel.
// I think this is faster than "t %= (format.bytesPerPixel * 8);" would be.
// I think this is faster than "t %= (ourFormat.bytesPerPixel * 8);" would be.
t &= (format.bytesPerPixel << 3) - 1;
t &= (ourFormat.bytesPerPixel << 3) - 1;


// Draw the actual gradient
// Draw the actual gradient
for (int16 y = 0; y < 480; y++) {
for (int16 y = 0; y < 480; y++) {
uint8 *dst = offscreenBuffer + (y * 640 * format.bytesPerPixel);
uint8 *dst = offscreenBuffer + (y * 640 * ourFormat.bytesPerPixel);
for (int16 x = 0; x < 640; x++) {
for (int16 x = 0; x < 640; x++) {
uint32 color = (x * y) & mask;
uint32 color = (x * y) & mask;
color = (color << t) | (color >> ((format.bytesPerPixel << 3) - t));
color = (color << t) | (color >> ((ourFormat.bytesPerPixel << 3) - t));


// Currently we have to jump through hoops to write variable-length data in an endian-safe manner.
// Currently we have to jump through hoops to write variable-length data in an endian-safe manner.
Line 127: Line 126:


#ifdef SCUMM_BIG_ENDIAN
#ifdef SCUMM_BIG_ENDIAN
for (int i = 0; i < format.bytesPerPixel; i++) {
for (int i = 0; i < ourFormat.bytesPerPixel; i++) {
dst[format.bytesPerPixel - i] = color & 0xFF;
dst[ourFormat.bytesPerPixel - i] = color & 0xFF;
color >>= 8;
color >>= 8;
}
}
dst += format.bytesPerPixel;
dst += ourFormat.bytesPerPixel;
#else
#else
for (int i = format.bytesPerPixel; i > 0; i--) {
for (int i = ourFormat.bytesPerPixel; i > 0; i--) {
*dst++ = color & 0xFF;
*dst++ = color & 0xFF;
color >>= 8;
color >>= 8;
Line 141: Line 140:
}
}
// Copy our gradient to the screen. The pitch of our image is the width * the number of bytes per pixel.
// Copy our gradient to the screen. The pitch of our image is the width * the number of bytes per pixel.
_system->copyRectToScreen(offscreenBuffer, 640 * format.bytesPerPixel, 0, 0, 640, 480);
_system->copyRectToScreen(offscreenBuffer, 640 * ourFormat.bytesPerPixel, 0, 0, 640, 480);


// Tell the system to update the screen.
// Tell the system to update the screen.
Line 206: Line 205:
=== Modified functions ===
=== Modified functions ===
====engine====
====engine====
*void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format = NULL)
*void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format)
**Can now take a format parameter, which is a pointer to a requested pixelformat, and defaults to NULL
**Now takes a format parameter, which is a pointer to a requested pixelformat
**Uses 256 color mode if format is NULL
**Uses top item in backend's getSupportedFormats list if format is NULL
**Now displays a warning if it recieves OSystem::kTransactionFormatNotSupported in return from endGFXTransaction
**Now displays a warning if it recieves OSystem::kTransactionFormatNotSupported in return from endGFXTransaction
**Now overloaded to simplify initialization for the three engine types:
*void initGraphics(int width, int height, bool defaultTo1xScaler)
**A wrapper which sets format as a pointer to Graphics::PixelFormat::createFormatCLUT8();
*void initGraphics(int width, int height, bool defaultTo1xScaler, const Commmon::List<Graphics::PixelFormat> &formatList)
**A wrapper which sets format as a pointer to the return value from Graphics::findCompatibleFormat(OSystem::getSupportedFormats(),formatList)


====OSystem====
====OSystem====
20

edits