Final Platform Layer 0.9.8-beta
Loading...
Searching...
No Matches
Software Output

Initialize a software backbuffer

To initialize software rendering output, you simply set the fplInitFlags_Video flag in the fplPlatformInit() call and change the video backend type to fplVideoBackendType_Software.
Call fplGetVideoBackBuffer() to get access to the pixel data.

fplSettings settings;
fplVideoSettings &videoSettings = settings.video;
// Forcing the video backend to be software
// Video software backbuffer is ready
}
fpl_common_api bool fplPlatformInit(const fplInitFlags initFlags, const fplSettings *initSettings)
Initializes the platform layer.
fpl_common_api void fplSetDefaultSettings(fplSettings *settings)
Resets the given settings container to default values for window, video, audio, etc.
@ fplInitFlags_Video
Use a video backbuffer (This flag ensures that fplInitFlags_Window is included always)
@ fplVideoBackendType_Software
Software.
fpl_common_api fplVideoBackBuffer * fplGetVideoBackBuffer()
Retrieves the pointer to the current video backbuffer.
A structure containing settings, such as window, video, etc.
fplVideoSettings video
Video settings.
A structure containing video backbuffer properties.
A structure that contains video settings such as backend, v-sync, API-settings, etc.
fplVideoBackendType backend
video backend type

Usage

To use the software backbuffer you simply access the fplVideoBackBuffer from the fplGetVideoBackBuffer() function and update the pixels as needed.

Presenting your frame

Call fplVideoFlip() to draw the pixels from the backbuffer to the window.
Its recommend to call this after each draw call of your frame at the end of the main-loop.

Drawing

Drawing is done by manually changing the pixels in the fplVideoBackBuffer::pixels field.
Each pixel is stored as 32-bit with 4 RGBA components in little-endian (AA BB GG RR).
Lines are stored in top-down order - meaning that position "0" in the fplVideoBackBuffer::pixels field is always the top-left corner of the bitmap!
To calculate the actual position for the current line, you simply multiply your Y-Index with the fplVideoBackBuffer::lineWidth field.

Example (Filling all pixels to purple):

for (uint32_t y = 0; y < backBuffer->height; ++y) {
uint32_t *p = (uint32_t *)((uint8_t *)backBuffer->pixels + y * backBuffer->lineWidth);
for (uint32_t x = 0; x < backBuffer->width; ++x) {
uint32_t color = 0xFFFF00FF;
*p++ = color;
}
}
uint32_t * pixels
The 32-bit pixel top-down array, format: 0xAABBGGRR. Do not modify before WindowUpdate.
uint32_t height
The height of the backbuffer in pixels. Do not modify, it will be set automatically.
size_t lineWidth
The width of one line in bytes. Do not modify, it will be set automatically.
uint32_t width
The width of the backbuffer in pixels. Do not modify, it will be set automatically.

Limiting the output rectangle (Stretching vs non-stretched)

To force the pixels to be shown in a fixed rectangle you simply enable the fplVideoBackBuffer::useOutputRect field and update the fplVideoBackBuffer::outputRect as needed.
This mimics a "viewport" which is similar to OpenGLs glViewport().

If you don't use this feature all pixels are fully stretched to the current window area always!

Note
This viewport should not be greater than the actual window area dimension!

Example (Resize window event):

static fplVideoRect ComputeLetterbox(int windowWidth, int windowHeight, int backWidth, int backHeight) {
return {};
}
backBuffer->useOutputRect = true;
while (fplWindowUpdate()) {
while (fplPollEvent(&ev)) {
fplVideoRect newRect = ComputeLetterbox(ev.window.width, ev.window.height, backBuffer->width, backBuffer->height); // ... Compute new rectangle here (Letterbox or something)
backBuffer->outputRect = newRect;
}
}
}
// ... Modify the pixels here (Draw call)
}
fpl_common_api void fplVideoFlip()
Forces the window to be redrawn or to swap the back/front buffer.
fpl_platform_api bool fplWindowUpdate()
Clears the internal event queue and updates input devices if needed.
fpl_platform_api bool fplPollEvent(fplEvent *ev)
Polls the next event from the internal event queue or from the OS, handles them, and removes it from ...
@ fplWindowEventType_Resized
Window has been resized.
@ fplEventType_Window
Window event.
A structure containing event data for all event types (Window, Keyboard, Mouse, etc....
fplWindowEvent window
Window event data.
fplEventType type
Event type.
fplVideoRect outputRect
The output rectangle for displaying the backbuffer (Size may not match backbuffer size!...
fpl_b32 useOutputRect
Set this to true to actually use the output rectangle.
A structure defining a video rectangles position and size.
fplWindowEventType type
Window event type.

Example (Always before the draw call):

backBuffer->useOutputRect = true;
while (fplWindowUpdate()) {
while (fplPollEvent(ev)) {}
fplVideoRect newRect = ComputeLetterbox(windowArea, backBuffer->width, backBuffer->height); // ... Compute new rectangle here (Letterbox or something)
backBuffer->outputRect = newRect;
// ... Modify the pixels here (Draw call)
}
fpl_platform_api bool fplGetWindowSize(fplWindowSize *outSize)
Retrieves the inner window size.
A structure containing the size of a window.

Resizing the backbuffer

By default, the video backbuffer is automatically resized when the dimension of the window area changes.
If you want to manually do this, you disable this feature in the fplVideoSettings::isAutoSize field - in the fplSettings::video configuration section.

Call fplResizeVideoBackBuffer() with a new width and height as an argument, to force the backbuffer to be resized to the new dimension.

Warning
Do not call this method while you are modifying pixels!

Notes

  • There is no software rendering functions built-in! If you want to draw for example a circle, you have to roll out your drawCircle() function - which may use Bresenham as its base or something.
  • Vertical synchronization is not supported for software video backends!