293 lines
9.2 KiB
D
293 lines
9.2 KiB
D
/**
|
|
* HULK Framebuffer support.
|
|
*/
|
|
module hulk.fb;
|
|
|
|
import hulk.memory;
|
|
import hulk.kfont;
|
|
|
|
/**
|
|
* Represent a graphical frame buffer.
|
|
*
|
|
* 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 side of rectangle.
|
|
* @param y Y coordinate of bottom side 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 side 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 bottom 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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw a character.
|
|
*
|
|
* @param x X coordinate of left side of character.
|
|
* @param y Y coordinate of bottom side of character.
|
|
* @param ch Character to draw.
|
|
* @param color Color of character.
|
|
*/
|
|
static void character(int x, int y, char ch, uint color)
|
|
{
|
|
const(CharInfo) * ci = &Kfont.chars[ch];
|
|
blend_alpha_bitmap(x + ci.left, y + Kfont.baseline_offset + ci.top - ci.height, ci.bitmap, ci.width, ci.height, color);
|
|
}
|
|
|
|
/**
|
|
* Blend an 8-bit alpha bitmap to the framebuffer.
|
|
*
|
|
* @param x X coordinate of left side of target location.
|
|
* @param y Y coordinate of bottom side of target location.
|
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
|
* @param width Bitmap width.
|
|
* @param height Bitmap height.
|
|
* @param color Color to blend with alpha value.
|
|
*/
|
|
static void blend_alpha_bitmap(size_t x, size_t y, const(ubyte) * alpha_bitmap,
|
|
size_t width, size_t height, uint color)
|
|
{
|
|
y += height - 1u;
|
|
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];
|
|
uint current_color = m_buffer1[buffer_index];
|
|
uint in_color_scaled = scale_color(color, alpha);
|
|
uint old_color_scaled = scale_color(current_color, 255u - alpha);
|
|
uint new_color = old_color_scaled + in_color_scaled;
|
|
m_buffer1[buffer_index] = new_color;
|
|
bitmap_index++;
|
|
}
|
|
memcpy32(&m_device_buffer[row_buffer_index], &m_buffer1[row_buffer_index], width);
|
|
y--;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Blend an 8-bit alpha bitmap to the framebuffer.
|
|
*
|
|
* @param x X coordinate of left side of target location.
|
|
* @param y Y coordinate of bottom side of target location.
|
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
|
* @param width Bitmap width.
|
|
* @param height Bitmap height.
|
|
* @param color Color to blend with alpha value.
|
|
*/
|
|
static void blend_alpha_bitmap(size_t x, size_t y, const(ubyte)[] alpha_bitmap,
|
|
size_t width, size_t height, uint color)
|
|
{
|
|
blend_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height, color);
|
|
}
|
|
|
|
/**
|
|
* 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 side of target location.
|
|
* @param y Y coordinate of bottom side 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)
|
|
{
|
|
y += height - 1u;
|
|
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 side of target location.
|
|
* @param y Y coordinate of bottom side 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 bottom side 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 + height + offset - 1u);
|
|
size_t src_buffer_index = buffer_index(0u, y + height - 1u);
|
|
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));
|
|
}
|
|
|
|
/**
|
|
* Scale a color value by an alpha amount.
|
|
*
|
|
* @param color Color value.
|
|
* @param alpha Alpha amount.
|
|
*
|
|
* @return Scaled color value.
|
|
*/
|
|
private static uint scale_color(uint color, ubyte alpha)
|
|
{
|
|
return ((((color & 0xFFu) * alpha) >> 8u) & 0xFFu) |
|
|
((((color & 0xFF00u) * alpha) >> 8u) & 0xFF00u) |
|
|
((((color & 0xFF0000u) * alpha) >> 8u) & 0xFF0000u);
|
|
}
|
|
|
|
/**
|
|
* 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 (m_height - y - 1u) * m_stride + x;
|
|
}
|
|
}
|