Subversion Repositories freemyipod

Rev

Blame | Last modification | View Log | RSS feed

#include "global.h"
#include "interface/lcd/lcd.h"
#include "interface/framebuffer/framebuffer.h"
#include "sys/util.h"

void lcd_init(const struct lcd_instance* instance)
{
    instance->driver->init(instance);
}

enum framebuffer_format lcd_get_native_format(const struct lcd_instance* instance)
{
    return instance->driver->get_native_format(instance);
}

void lcd_power(const struct lcd_instance* instance, bool on)
{
    instance->driver->power(instance, on);
}

void lcd_backlight(const struct lcd_instance* instance, int brightness)
{
    instance->driver->backlight(instance, brightness);
}

void lcd_setup_range(const struct lcd_instance* instance, int x, int y, int w, int h)
{
    instance->driver->setup_range(instance, x, y, w, h);
}

void lcd_fill_pixels(const struct lcd_instance* instance, uint32_t color, int count)
{
    instance->driver->fill_pixels(instance, color, count);
}

void lcd_blit_pixels(const struct lcd_instance* instance, void* buffer, int count)
{
    instance->driver->blit_pixels(instance, buffer, count);
}

void lcd_fill(const struct lcd_instance* instance, int x, int y, int w, int h,
              enum framebuffer_format format, uint32_t color, enum framebuffer_conversion_quality quality)
{
    enum framebuffer_format native = lcd_get_native_format(instance);
    if (format != native)
    {
        if (framebuffer_format_wordsize[format] == 16) color = swap16(color);
        else if (framebuffer_format_wordsize[format] == 32) color = swap32(color);
        color = framebuffer_convert_color(format, native, color);
        if (framebuffer_format_wordsize[native] == 16) color = swap16(color);
        else if (framebuffer_format_wordsize[native] == 32) color = swap32(color);
    }
    lcd_setup_range(instance, x, y, w, h);
    lcd_fill_pixels(instance, color, w * h);
}

void lcd_blit(const struct lcd_instance* instance, int x, int y, int w, int h,
              const struct framebuffer_instance* framebuffer, int fx, int fy, enum framebuffer_conversion_quality quality)
{
    int stride = framebuffer->width;
    enum framebuffer_format infmt = framebuffer->format;
    enum framebuffer_format outfmt = lcd_get_native_format(instance);
    int inwsize = framebuffer_format_wordsize[infmt];
    int outwsize = framebuffer_format_wordsize[outfmt];

    lcd_setup_range(instance, x, y, w, h);

    if (w == stride)
    {
        w *= h;
        h = 1;
    }

    if (infmt == outfmt && inwsize >= 8)
    {
        void* in = framebuffer->data + (fy * stride + fx) * (inwsize >> 3);
        while (h--)
        {
            lcd_blit_pixels(instance, in, w);
            in += (stride - w) * (inwsize >> 3);
        }
        return;
    }

    int inmask = 0xffffffff >> (32 - inwsize);
    uint32_t* in = framebuffer->data;
    int inbit = (fy * stride + fx) * inwsize;
    in += inbit >> 5;
    inbit &= 31;
    uint32_t buf[64];
    while (h--)
    {
        int pixels = w;
        uint32_t idata = swap32(*in) << inbit;
        while (pixels > 0)
        {
            int processed = 0;
            uint32_t* out = buf;
            int outbit = 0;
            uint32_t odata;
            while (((void*)out) < ((void*)buf) + sizeof(buf) && processed < pixels)
            {
                if (inbit == 32)
                {
                    idata = swap32(*++in);
                    inbit = 0;
                }
                if (!outbit) odata = 0;
                idata = ((idata << inwsize) | (idata >> (32 - inwsize)));
                odata <<= outwsize;
                uint32_t data = idata & inmask;
                if (infmt != outfmt) data = framebuffer_convert_color(infmt, outfmt, data);
                odata |= data;
                inbit += inwsize;
                outbit += outwsize;
                if (outbit == 32)
                {
                    *out++ = swap32(odata);
                    outbit = 0;
                }
                processed++;
            }
            if (outbit) *out = swap32(odata << (32 - outbit));
            lcd_blit_pixels(instance, buf, processed);
            pixels -= processed;
        }
        inbit += (stride - w) * inwsize;
        in += inbit >> 5;
        inbit &= 31;
    }
}

void lcd_fb_update_handler(const void* arg, const struct framebuffer_instance* fb, int x, int y, int w, int h)
{
    const struct lcd_instance* instance = (const struct lcd_instance*)arg;
    lcd_blit(instance, x, y, w, h, fb, x, y, FRAMEBUFFER_CONVERSION_QUALITY_CLIP);
}