243 lines
7.4 KiB
D
243 lines
7.4 KiB
D
/**
|
|
* HULK Framebuffer support.
|
|
*/
|
|
module hulk.fb;
|
|
|
|
import hulk.memory;
|
|
import hulk.kfont;
|
|
|
|
/**
|
|
* Represent a graphical frame buffer.
|
|
*
|
|
* Coordinate (0,0) is the top-left corner of the framebuffer.
|
|
*
|
|
* TODO: Handle other pixel formats. Currently only BGRx is supported.
|
|
*/
|
|
struct Fb
|
|
{
|
|
/** Device frame buffer base address. */
|
|
private __gshared static uint * m_device_buffer;
|
|
|
|
/** Frame buffer 1 base address. */
|
|
private __gshared static uint * m_buffer1;
|
|
|
|
/** Frame buffer width. */
|
|
private __gshared static uint m_width;
|
|
|
|
/** Frame buffer height. */
|
|
private __gshared static uint m_height;
|
|
|
|
/** Frame buffer stride. */
|
|
private __gshared static uint m_stride;
|
|
|
|
/** Number of pixels in the frame buffer (whether visible or not). */
|
|
private __gshared static uint m_buffer_size;
|
|
|
|
/**
|
|
* Get the framebuffer width.
|
|
*/
|
|
public static @property uint width()
|
|
{
|
|
return m_width;
|
|
}
|
|
|
|
/**
|
|
* Get the framebuffer height.
|
|
*/
|
|
public static @property uint height()
|
|
{
|
|
return m_height;
|
|
}
|
|
|
|
/**
|
|
* Initialize a frame buffer.
|
|
*
|
|
* @param device_buffer Device frame buffer base address.
|
|
* @param buffer1 Frame buffer 1 base address.
|
|
* @param width Frame buffer width.
|
|
* @param height Frame buffer height.
|
|
* @param stride Frame buffer stride.
|
|
*/
|
|
static void initialize(uint * device_buffer, uint * buffer1, uint width, uint height, uint stride)
|
|
{
|
|
m_device_buffer = device_buffer;
|
|
m_buffer1 = buffer1;
|
|
m_width = width;
|
|
m_height = height;
|
|
m_stride = stride;
|
|
m_buffer_size = stride * height;
|
|
}
|
|
|
|
/**
|
|
* Clear the frame buffer to the given color.
|
|
*
|
|
* @param color Color to clear to.
|
|
*/
|
|
static void clear(uint color = 0u)
|
|
{
|
|
memset32(m_buffer1, color, m_buffer_size);
|
|
memset32(m_device_buffer, color, m_buffer_size);
|
|
}
|
|
|
|
/**
|
|
* Draw a solid rectangle on the framebuffer.
|
|
*
|
|
* @param x X coordinate of left of rectangle.
|
|
* @param y Y coordinate of top of rectangle.
|
|
* @param width Width of rectangle.
|
|
* @param height Height of rectangle.
|
|
* @param color Color of rectangle.
|
|
*/
|
|
static void rect(size_t x, size_t y, size_t width, size_t height, uint color)
|
|
{
|
|
for (size_t iy = 0u; iy < height; iy++)
|
|
{
|
|
size_t buffer_index = buffer_index(x, y);
|
|
memset32(&m_buffer1[buffer_index], color, width);
|
|
memset32(&m_device_buffer[buffer_index], color, width);
|
|
y++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw a horizontal line.
|
|
*
|
|
* @param x X coordinate of left of line.
|
|
* @param y Y coordinate of line.
|
|
* @param width Width of line.
|
|
* @param color Color of line.
|
|
*/
|
|
static void hline(size_t x, size_t y, size_t width, uint color)
|
|
{
|
|
size_t buffer_index = buffer_index(x, y);
|
|
memset32(&m_buffer1[buffer_index], color, width);
|
|
memset32(&m_device_buffer[buffer_index], color, width);
|
|
}
|
|
|
|
/**
|
|
* Draw a vertical line.
|
|
*
|
|
* @param x X coordinate of line.
|
|
* @param y Y coordinate of top of line.
|
|
* @param height Height of line.
|
|
* @param color Color of line.
|
|
*/
|
|
static void vline(size_t x, size_t y, size_t height, uint color)
|
|
{
|
|
size_t buffer_index = buffer_index(x, y);
|
|
for (size_t iy = 0u; iy < height; iy++)
|
|
{
|
|
m_buffer1[buffer_index] = color;
|
|
m_device_buffer[buffer_index] = color;
|
|
buffer_index += m_stride;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Blit an 8-bit alpha bitmap to the framebuffer.
|
|
* The foreground will be white (based on the alpha value), and the
|
|
* background black.
|
|
*
|
|
* @param x X coordinate of left of target location.
|
|
* @param y Y coordinate of top of target location.
|
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
|
* @param width Bitmap width.
|
|
* @param height Bitmap height.
|
|
*/
|
|
static void blit_alpha_bitmap(size_t x, size_t y, const(ubyte) * alpha_bitmap,
|
|
size_t width, size_t height)
|
|
{
|
|
size_t bitmap_index;
|
|
for (size_t iy = 0u; iy < height; iy++)
|
|
{
|
|
size_t row_buffer_index = buffer_index(x, y);
|
|
for (size_t ix = 0u; ix < width; ix++)
|
|
{
|
|
size_t buffer_index = row_buffer_index + ix;
|
|
ubyte alpha = alpha_bitmap[bitmap_index];
|
|
m_buffer1[buffer_index] = (alpha << 16u) | (alpha << 8u) | alpha;
|
|
bitmap_index++;
|
|
}
|
|
memcpy32(&m_device_buffer[row_buffer_index], &m_buffer1[row_buffer_index], width);
|
|
y++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Blit an 8-bit alpha bitmap to the framebuffer.
|
|
* The foreground will be white (based on the alpha value), and the
|
|
* background black.
|
|
*
|
|
* @param x X coordinate of left of target location.
|
|
* @param y Y coordinate of top of target location.
|
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
|
* @param width Bitmap width.
|
|
* @param height Bitmap height.
|
|
*/
|
|
static void blit_alpha_bitmap(size_t x, size_t y, const(ubyte)[] alpha_bitmap,
|
|
size_t width, size_t height)
|
|
{
|
|
blit_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height);
|
|
}
|
|
|
|
/**
|
|
* Copy framebuffer rows up in the framebuffer.
|
|
*
|
|
* @param y Y coordinate of top of region to copy up.
|
|
* @param height Height of region to copy up.
|
|
* @param offset Number of rows to copy region up by.
|
|
*/
|
|
static void copy_rows_up(size_t y, size_t height, size_t offset)
|
|
{
|
|
size_t dest_buffer_index = buffer_index(0u, y - offset);
|
|
size_t src_buffer_index = buffer_index(0u, y);
|
|
memcpy32(&m_buffer1[dest_buffer_index],
|
|
&m_buffer1[src_buffer_index],
|
|
(m_stride * height));
|
|
memcpy32(&m_device_buffer[dest_buffer_index],
|
|
&m_buffer1[dest_buffer_index],
|
|
(m_stride * height));
|
|
}
|
|
|
|
/**
|
|
* Copy a rectangle in the framebuffer.
|
|
*
|
|
* @param sx X coordinate of left of source rectangle.
|
|
* @param sy Y coordinate of top of source rectangle.
|
|
* @param width Width of rectangle to copy.
|
|
* @param height Height of rectangle to copy.
|
|
* @param dx X coordinate of left of destination rectangle.
|
|
* @param dy Y coordinate of top of destination rectangle.
|
|
*/
|
|
static void copy_rect(size_t sx, size_t sy, size_t width, size_t height,
|
|
size_t dx, size_t dy)
|
|
{
|
|
size_t dest_buffer_index = buffer_index(dx, dy);
|
|
size_t src_buffer_index = buffer_index(sx, sy);
|
|
for (size_t y = 0u; y < height; y++)
|
|
{
|
|
memcpy32(&m_buffer1[dest_buffer_index],
|
|
&m_buffer1[src_buffer_index],
|
|
width);
|
|
memcpy32(&m_device_buffer[dest_buffer_index],
|
|
&m_buffer1[dest_buffer_index],
|
|
width);
|
|
dest_buffer_index += m_stride;
|
|
src_buffer_index += m_stride;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the buffer index for the given X and Y coordinates.
|
|
*
|
|
* @param x X coordinate from left side of framebuffer.
|
|
* @param y Y coordinate from bottom side of framebuffer.
|
|
*
|
|
* @return Buffer index for the given X and Y coordinates.
|
|
*/
|
|
private static size_t buffer_index(size_t x, size_t y)
|
|
{
|
|
return y * m_stride + x;
|
|
}
|
|
}
|