ScummVM RGB color progress blog

June 27, 2009

finalized API function reference:

Filed under: Planning,Progress — Upthorn @ 12:01 am

So here is the skinny on the pixel format request API :

  • static inline Graphics::PixelFormat Graphics::PixelFormat::createFormat*(void)
    • creates a PixelFormat and initializes it to the specified format. A list of formats provided follows:
      • createFormatCLUT8() // 256 color paletted
      • createFormatRGBA4444()
      • createFormatARGB4444()
      • createFormatABGR4444()
      • createFormatBGRA4444()
      • createFormatRGB555() //16bit 555 RGB
      • createFormatBGR555()
      • createFormatXRGB1555() //only use these if you need the backend to handle alpha
      • createFormatXBGR1555() //otherwise use the 555 versions, instead of 1555
      • createFormatRGB565()
      • createFormatBGR565()
      • createFormatRGB888() // when 24 and 32-bit modes are supported
      • createFormatBGR888() // when 24 and 32-bit modes are supported
      • createFormatRGBA8888() // when 24 and 32-bit modes are supported
      • createFormatARGB8888() // when 24 and 32-bit modes are supported
      • createFormatABGR8888() // when 24 and 32-bit modes are supported
      • createFormatBGRA8888() // when 24 and 32-bit modes are supported
    • Because these methods are static, they can be called before the object is defined, E.G.:
      • Graphics::PixelFormat _screenFormat = Graphics::PixelFormat::createFormatRGB555();
  • void initGraphics(int width, int height, bool defaultTo1xScaler, Graphics::PixelFormat *format = NULL)
    • format is a pointer to a Graphics::PixelFormat describing the pixel format requested of the backend.
    • if format is left as NULL, CLUT8 will be used.
  • Common::List<Graphics::PixelFormat> OSystem::getSupportedFormats(void)
    • returns a list of all pixel formats supported by the backend
    • Backends supporting non-paletted color data must support data in native hardware color order, and should support data RGBA color order.
    • All backends are required to support data in CLUT8 (256 color palette) format.
    • The first item in the list (List.begin()) must always be the pixelformat which provides the greatest RGB colorspace that is directly supported by hardware
      • on dreamcast, this would be Graphics::PixelFormat::createFormatRGB565
      • on PSP, this would be Graphics::PixelFormat::createFormatABGR8888 once 32-bit modes are supported by scalers, and Graphics::PixelFormat::createFormatBGR565 until then.
    • The rest of the list shall be ordered by preference of backend
      • If the backend can convert color orders quickly, larger colorspace formats should be first.
      • An ABGR-preferred SDL system with fast conversion would order like this:
        1. createFormatBGR565()
        2. createFormatRGB565()
        3. createFormatXBGR1555()
        4. createFormatXRGB1555()
        5. createFormatBGR555()
        6. createFormatRGB555()
        7. createFormatBGRA4444()
        8. createFormatABGR4444()
        9. createFormatARGB4444()
        10. createFormatRGBA4444()
        11. createFormatCLUT8()
        • That is, larger colorspace first, equivalent colorspaces ordered by hardware support.
      • Whereas a similarly capable system with slower conversion would order like this:
        1. createFormatBGR565()
        2. createFormatXBGR1555()
        3. createFormatBGR555()
        4. createFormatBGRA4444()
        5. createFormatCLUT8()
        6. createFormatRGB565()
        7. createFormatXRGB1555()
        8. createFormatRGB555()
        9. createFormatRGBA4444()
        10. createFormatABGR4444()
        11. createFormatARGB4444()
        • That is, hardware supported RGB formats first, equivalently supported formats ordered by size of colorspace
    • Note: aside from the guarantee that the first item is directly supported in hardware, there is no way for an engine to determine whether or not any given format on the list is hardware supported. This is the reason that list ordering is important: the engine will use the first item in the list that it is compatible with.
  • Graphics::PixelFormat OSystem::getScreenFormat(void)
    • Returns the pixel format the game screen is currently initialized for.
  • virtual void OSystem::initSize(uint width, uint height, Graphics::PixelFormat *format = NULL)
    • initializes the size and pixel format of the game screen.
    • if format is left as NULL, a new Graphics::PixelFormat will be created, and initialized to CLUT8.
    • this is changed from the separate initFormat that was specified when I did not realize GFX transactions were an optional feature.
  • OSystem::TransactionError OSystem::endGFXTransaction(void)
    • backends supporting GFX transactions will return kTransactionFormatNotSupported in the list of transaction errors, when they are unable to initialize the screen with the requested format.
  • Graphics::PixelFormat Graphics::findCompatibleFormat(Common::List<Graphics::PixelFormat> backend, Common::List<Graphics::PixelFormat> frontend)
    • Returns the first entry on the backend list that also occurs in the frontend list, or CLUT8 if there is no matching format.
  • void Graphics::CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, Graphics::PixelFormat *format)
    • format is a pointer to a Graphics::PixelFormat describing the pixel format of the cursor graphic.
    • if format is left as NULL, CLUT8 will be used.
  • void Graphics::CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, Graphics::PixelFormat *format)
    • format is a pointer to a Graphics::PixelFormat describing the pixel format of the cursor graphic.
    • if format is left as NULL, a new Graphics::PixelFormat will be created, and initialized to CLUT8.
  • Graphics::CursorManager::Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, Graphics::PixelFormat *format = NULL)
    • format is a pointer to a Graphics::PixelFormat describing the pixel format of the cursor graphic.
    • if format is left as NULL, a new Graphics::PixelFormat will be created, and initialized to CLUT8.

This is how initialization works:

  • Engine side:
    • Case 1: Game runs in 8-bit paletted mode
      1. No changes are necessary.
    • Case 2: Game runs in a specific high/true color format
      1. engine calls initGraphics with that format
      2. engine calls OSystem::getScreenFormat() to check resulting format against requested format
        • Case A: getScreenFormat() returns requested format
          1. engine runs happily
        • Case B: getScreenFormat() returns CLUT8 and engine has an 8-bit fallback mode
          1. engine switches to fallback mode
          2. engine runs in 8-bits
        • Case C: getScreenFormat() returns CLUT8 and engine doesn’t have fallback mode
          1. engine displays error and returns immediately
        • Case D: getScreenFormat() returns a format that is neither CLUT8 nor the requested format
          1. Tester submits bug report to backend maintainer
          2. Backend maintainer ensures that CLUT8 is the only unrequested mode that backend will fallback to.
    • Case 3: Game can support any RGB mode easily
      1. engine calls OSystem::getSupportedFormats()
      2. engine calls initGraphics with the top list item.
      3. engine calls OSystem::getScreenFormat() to ensure that format is usable properly at requested resolution
        • see cases 2A – 2D
    • Case 4: Game can run in a small number of RGB modes
      1. engine calls OSystem::getSupportedFormats() to get list of formats supported by backend
      2. engine produces list of formats game can run in
      3. engine calls Graphics::findCompatibleFormat(backend_list, engine_list)
      4. engine calls initGraphics with return value from findCompatibleFormat
      5. engine calls OSystem::getScreenFormat() to ensure that format is usable properly at requested resolution
        • see cases 2A – 2D
  • Backend side:
    • backend recieves screen’s requested resolution and format from initGraphics
      • Case 1: NULL pointer
        1. backend initializes screen to 8-bit graphics at requested resolution.
      • Case 2: Hardware directly supports format at requested resolution
        1. backend initializes screen to requested format at requested resolution.
      • Case 3: Hardware supports format at requested resolution, in a different color order
        • Case A: Requested format is RGBA or another conversion-supported color order
          1. backend initializes screen to corrected-order format equivalent at requested resolution.
          2. Backend implements pixel conversion on copyRectToScreen, preferably using ASM hand-crafted for speed.
          3. getScreenFormat will “lie” and return the requested format, rather than the hardware-supported equivalent that is actually being used.
        • Case B: Requested format is GABR or similarly nonsensical/unsupported color order
          1. backend initializes screen to 8-bit graphics at requested resolution.
      • Case 4: Hardware does not support format
        • Case A: requested format has alpha component and hardware supports equivalently-aligned format without alpha
          1. Backend initializes screen to alpha-less equivalent format at requested resolution.
          2. Backend implements alpha blending in software.
          3. getScreenFormat will “lie” and return the requested format, rather than the hardware-supported equivalent that is actually being used.
        • Case B: hardware supports higher format, backend can easily up-convert (optional case, to be handled at backend maintainer’s disgression)
          1. backend initializes screen to higher format.
          2. backend implements up-conversion on copyRectToScreen.
          3. getScreenFormat will “lie” and return the requested format, rather than the hardware-supported equivalent that is actually being used.
        • Case C: all other cases
          1. backend initializes screen to 8-bit graphics at requested resolution.
      • Case 5: Hardware supports format but not at requested resolution
        1. backend initializes screen to 8-bit graphics at requested resolution.
Advertisements

1 Comment »

  1. Hi,

    First of all, congratulations. Your work is is looking great and it’s an important contribution to ScummVM ;)

    Here are some doubts I have from the engine developer point of view:

    – I see some methods (like getScreenFormat and getSupportedFormats) are just defined when the backend is compiled with support for RGB modes though they also make sense when compiled without RGB support (just returning CLUT8) with the only overhead being a tiny executable size increase. This would allow simplifying the engines that can work in both RGB and indexed modes by removing some #ifdef’s on the initialization code. Are you restricting it for some other reason?

    – I’ve read that some backends can change their pixel format while running (like Mac OS X when changing to fullscreen mode), but engines weren’t affected since they ran in 8bit modes and the backend did the conversion transparently. Does the new API guarantee the screen pixel format won’t change or should the engine be prepared to handle these changes? In the later case it should be properly documented.

    – The mouse cursor API is where I miss most details: Can the mouse cursor’s pixel format be different than the screen one? Would the backend be responsible of doing the conversion in that case? Will the mouse cursor’s alpha bits be used to blend it or they will simply be ignored?

    This last point is particularly interesting for me since some cursors for the later games in the groovie engine are semi-transparent, and their pixel format will probably be fixed (we haven’t deciphered their format yet) while having the rest of the images converted to the optimal format.

    Hoping to hear from you soon!

    Comment by Jordi Vilalta — June 29, 2009 @ 3:57 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: