Plan for new graphics rendering
This represents the plan for improved graphics rendering, utilizing arbitrarily transformed quad rasterization. The goal here is to detail the new interfaces that each backend can implement.
Surface
A Surface is an array of "pixels" that is width x height in length. A Surface must have the following:
- handle
- width
- height
- format
- usage
- data pointer
where handle is a reference to a hardware implementation (if present), and where format is the data type of the pixel: either 8bit or 32bit; and usage can be one of the following:
- source
- render target
The source type is the typical usage where the Surface is used as the "texture" to sample in rendering. It can also be used as the source in a surface blit operation. Source surfaces are the only type that can directly manipulated at the pixel level. The render target type is for rendering transformed quads to it's surface, and being a destination target in a surface blit operation. By contrast, the normal source type cannot be the target of such operations. Render targets can also be used as a source texture in another operation.
Why the distinction? Certain hardware acceleration techniques can optimize a certain resource type's usage. The software rasterizer does not take advantage of this case, however, so it will ignore the usage type.
The data pointer will contain a pointer to the raw data. If there is hardware acceleration, this will still be a valid array for source surfaces--however the hardware surface will not be updated without an appropriate call.
Interfaces
Following is a list of suggested interfaces:
gfx_surfaceCreate( width, height, format, usage, pSurfaceOut ) gfx_surfaceDestroy( pSurfaceIn ) gfx_surfaceUpdate( pSurfaceIn ) gfx_surfaceFill( color, pRect, pSurfaceIn ) gfx_surfaceStretch( pRectSrc, pSurfaceSrc, pRectDest, pSurfaceDest, pPalette ) gfx_surfaceStretchWithColorKey( pRectSrc, pSurfaceSrc, pRectDest, pSurfaceDest, pPalette, colorKey ) gfx_surfaceCopy( pRectSrc, pSurfaceSrc, pRectDest, pSurfaceDest, pPalette ) gfx_surfaceCopyWithColorKey( pRectSrc, pSurfaceSrc, pRectDest, pSurfaceDest, pPalette, colorKey )
gfx_surfaceCreate
This function will simply create a surface with the data values. In software, it'll be roughly implemented as:
int gfx_surfaceCreate( int width, int height, enum SurfaceFormat fmt, enum SurfaceUsage usage, Surface* pSurfaceOut ) { if( !pSurfaceOut ) return -1; Surface temp = {width, height, fmt, usage}; if(fmt == SF_32bit) temp.pData = (void*)new unsigned long[width*height]; else temp.pData = (void*)new unsigned char[width*height]; g_surfaceList.push_back(temp); pSurfaceOut = &g_surfaceList.back(); return 0; }
gfx_surfaceDestroy
This function will destroy a surface.
int gfx_surfaceDestroy( Surface* pSurfaceIn ) { //validate input //find the list item //delete it from the list }
gfx_surfaceUpdate
This function is important only to hardware accelerated backends, as they are rendering from a separate, copied surface data. It's implementation in software is simply returning success. A typical scenario where this would be needed is if individual pixels are changed. Only source surfaces can be updated.
gfx_surfaceFill
The fill function clears a section of the surface to a color. The render target usage of surface is an acceptable destination surfaces.
gfx_surfaceStretch
This function will stretch one surface on top of another, possibly scaling it horizontally and vertically. The render target usage of surface is an acceptable destination surfaces. Both source and render target usage can be an input surface. Also, if the source format is 8bit, and the destination format is 32bit, an optionally passed in palette will be used to convert the formats. However, a 32bit source and 8bit destination surface will fail.
gfx_surfaceStretchWithColorKey
This function is the same as gfx_surfaceStretch, except it expects the source surface to be 8bit. Also if the source pixel has the value of colorKey, it will not be copied over. If the destination surface is 32bit, it will convert to 32bit using the optionally passed in palette.
gfx_surfaceCopy
This function will simply blit one surface onto another. The render target usage of surface is an acceptable destination surfaces. Both source and render target usage can be an input surface. Also, if the source format is 8bit, and the destination format is 32bit, an optionally passed in palette will be used to convert the formats. However, a 32bit source and 8bit destination surface will fail.
gfx_surfaceCopyWithColorKey
This function is the same as gfx_surfaceCopy, except it expects the source surface to be 8bit. Also if the source pixel has the value of colorKey, it will not be copied over. If the destination surface is 32bit, it will convert to 32bit using the optionally passed in palette.
Palette's
A palette is an array of 256 numbers, each 32bits. They are used in rendering methods. They are defined as:
- handle
- palette array
where handle is a reference to a hardware implementation, if available.
Interfaces
The suggested interfaces for managing palettes include:
gfx_paletteCreate( pPaletteOut ) gfx_paletteDestroy( pPaletteIn ) gfx_paletteUpdate( pPaletteIn )
gfx_paletteCreate
This function simply creates a palette. In software, this is the equivalent of simply adding a structure containing a 256-entry array to an internal list, and returning a pointer to it.
gfx_paletteDestroy
This function just removes the palette from the list.
gfx_paletteUpdate
This function would typically be called when at least one entry is altered. This is important for hardware accelerated backends. In software rendering, it will simply return success.
Quad
A Quad, short for quadrilateral, is the entity that can be arbitrarily transformed and rendered. It's structure is simply:
struct Quad { Vertex v[4]; };
Each vertex represents a corner of the quad, in clockwise or counterclockwise order. The vertex format is of debate right now, but it may contain the following data:
- position (x,y)
- texture coordinates (u,v)
- vertex color
Quad's have to be rendered onto surfaces. Thus, surfaces created with the source usage are not valid targets. (Even though the software rasterizer can render to them, it shouldn't be done.) Only render target usage type is valid for being rendered to.
Interfaces
Quad's are a data type managed by the engine. Because quad's typically have textures (or sampled surfaces) associated with them, and those surfaces may potentially be paletted, the interfaces are written accordingly:
gfx_renderQuadTexture( pQuad, pTexture, pPalette, argbModifier, pRectDest, pSurfaceDest ) gfx_renderQuadTextureWithColorKey( pQuad, pTexture, pPalette, colorKey, argbModifier, pRectDest, pSurfaceDest ) gfx_renderQuadColor( pQuad, argbModifier, pRectDest, pSurfaceDest )
gfx_renderQuadTexture
This function will take a quad and interpolate the texture coord's across it's face during rasterization, using the pTexture as the source texture with pPalette as the palette table (if pTexture is an 8bit surface and if pSurfaceDest is not an 8bit surface). The argbModifier is a 32bit number containing scaling information to scale each of the colors a, r, g, and b. The optional pRectDest can designate a clipping region on the surface. The pSurfaceDest must be a render target usage type.
In hardware acceleration, this will typically need the device context before it can operate correctly.
gfx_renderQuadTextureWithColorKey
Same as gfx_renderQuadTexture(), except this function expects the source texture to be 8bit. If the value of a sampled pixel is colorKey, the pixel will be discarded for rendering.
gfx_renderQuadColor
Same as gfx_renderQuadTexture(), though without texture sampling. Again, in hardware acceleration, this will need the device context before it can operate correctly.
Presenting the Backbuffer
The backbuffer is a special type of surface which can only be rendered/copied to, for it will be drawn on the screen. It cannot be the source surface in any function. When all rendering is complete, the surface should be copied to from a render target and then presented as:
gfx_present( pSurfaceIn, pPalette )
where pSurfaceIn is a render target or source surface. If they are in 8bit format, a passed in palette will be used to convert to 32bit.
Hardware acceleration requirements
In hardware accelerated backends, the two quad-rendering functions need to have the device context obtained before successfully operating. To do this, two interfaces are exposed:
gfx_renderBegin() gfx_renderEnd()
gfx_renderBegin marks the beginning of a number of quad rendering calls, and gfx_renderEnd marks the end. They cannot be nested, and they cannot be called again until a presentation of the backbuffer is made.