diff --git a/devices/video/atimach64gx.cpp b/devices/video/atimach64gx.cpp index 8e7e0df..2316942 100644 --- a/devices/video/atimach64gx.cpp +++ b/devices/video/atimach64gx.cpp @@ -299,7 +299,7 @@ void AtiMach64Gx::enable_crtc_internal() switch (this->pixel_depth) { case 8: this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) { - this->convert_frame_8bpp(dst_buf, dst_pitch); + this->convert_frame_8bpp_indexed(dst_buf, dst_pitch); }; break; default: diff --git a/devices/video/atirage.cpp b/devices/video/atirage.cpp index 1d038b0..451cc75 100644 --- a/devices/video/atirage.cpp +++ b/devices/video/atirage.cpp @@ -551,7 +551,7 @@ void ATIRage::crtc_update() { ABORT_F("%s: DAC_DIRECT set!", this->name.c_str()); } this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) { - this->convert_frame_8bpp(dst_buf, dst_pitch); + this->convert_frame_8bpp_indexed(dst_buf, dst_pitch); }; break; default: diff --git a/devices/video/control.cpp b/devices/video/control.cpp index 3f6a196..4c2612c 100644 --- a/devices/video/control.cpp +++ b/devices/video/control.cpp @@ -267,7 +267,7 @@ void ControlVideo::enable_display() if (pixel_depth == 8) { this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) { - this->convert_frame_8bpp(dst_buf, dst_pitch); + this->convert_frame_8bpp_indexed(dst_buf, dst_pitch); }; } else { ABORT_F("Control: 16bpp and 32bpp formats not supported yet!"); diff --git a/devices/video/pdmonboard.cpp b/devices/video/pdmonboard.cpp index 2daa62a..2d85828 100644 --- a/devices/video/pdmonboard.cpp +++ b/devices/video/pdmonboard.cpp @@ -121,13 +121,13 @@ void PdmOnboardVideo::set_depth_internal(int pitch) switch (this->pixel_depth) { case 1: this->convert_fb_cb = [this](uint8_t* dst_buf, int dst_pitch) { - this->convert_frame_1bpp(dst_buf, dst_pitch); + this->convert_frame_1bpp_indexed(dst_buf, dst_pitch); }; this->fb_pitch = pitch >> 3; // one byte contains 8 pixels break; case 8: this->convert_fb_cb = [this](uint8_t* dst_buf, int dst_pitch) { - this->convert_frame_8bpp(dst_buf, dst_pitch); + this->convert_frame_8bpp_indexed(dst_buf, dst_pitch); }; this->fb_pitch = pitch; // one byte contains 1 pixel break; @@ -239,7 +239,7 @@ void PdmOnboardVideo::disable_video_internal() CLUT entry #127 (%01111111) and a black pixel to #255 (%11111111). It requres a non-standard conversion routine implemented below. */ -void PdmOnboardVideo::convert_frame_1bpp(uint8_t *dst_buf, int dst_pitch) +void PdmOnboardVideo::convert_frame_1bpp_indexed(uint8_t *dst_buf, int dst_pitch) { uint8_t *src_buf, *src_row, pix; uint32_t *dst_row; diff --git a/devices/video/pdmonboard.h b/devices/video/pdmonboard.h index 2209804..b8aac9f 100644 --- a/devices/video/pdmonboard.h +++ b/devices/video/pdmonboard.h @@ -72,7 +72,7 @@ protected: void set_depth_internal(int pitch); void enable_video_internal(); void disable_video_internal(); - void convert_frame_1bpp(uint8_t *dst_buf, int dst_pitch); + void convert_frame_1bpp_indexed(uint8_t *dst_buf, int dst_pitch); private: uint8_t video_mode; diff --git a/devices/video/videoctrl.cpp b/devices/video/videoctrl.cpp index da2ff9c..780f31b 100644 --- a/devices/video/videoctrl.cpp +++ b/devices/video/videoctrl.cpp @@ -136,26 +136,304 @@ void VideoCtrlBase::setup_hw_cursor(int cursor_width, int cursor_height) this->cursor_on = true; } -void VideoCtrlBase::convert_frame_1bpp(uint8_t *dst_buf, int dst_pitch) +void VideoCtrlBase::convert_frame_1bpp_indexed(uint8_t *dst_buf, int dst_pitch) { - // TODO: implement me! -} - -void VideoCtrlBase::convert_frame_8bpp(uint8_t *dst_buf, int dst_pitch) -{ - uint8_t *src_buf, *src_row, *dst_row; + uint8_t *src_row, *dst_row; int src_pitch; - src_buf = this->fb_ptr; - src_pitch = this->fb_pitch; + src_pitch = this->fb_pitch - ((this->active_width + 7) >> 3); + dst_pitch = dst_pitch - 4 * this->active_width; - for (int h = 0; h < this->active_height; h++) { - src_row = &src_buf[h * src_pitch]; - dst_row = &dst_buf[h * dst_pitch]; - - for (int x = 0; x < this->active_width; x++) { - WRITE_DWORD_LE_A(dst_row, this->palette[src_row[x]]); + src_row = this->fb_ptr - 1; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + uint8_t bit = 0x00; + uint8_t c; + for (int x = this->active_width; x > 0; x--) { + if (!bit) { + src_row += 1; + bit = 0x80; + c = *src_row; + } + WRITE_DWORD_LE_A(dst_row, this->palette[!!(c & bit)]); + bit >>= 1; dst_row += 4; } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +void VideoCtrlBase::convert_frame_2bpp_indexed(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - (this->active_width >> 2); + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + uint8_t c; + for (int x = this->active_width >> 2; x > 0; x--) { + c = *src_row; + WRITE_DWORD_LE_A(dst_row, this->palette[c >> 6]); + dst_row += 4; + WRITE_DWORD_LE_A(dst_row, this->palette[(c >> 4) & 3]); + dst_row += 4; + WRITE_DWORD_LE_A(dst_row, this->palette[(c >> 2) & 3]); + dst_row += 4; + WRITE_DWORD_LE_A(dst_row, this->palette[c & 3]); + dst_row += 4; + src_row += 1; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +void VideoCtrlBase::convert_frame_4bpp_indexed(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - (this->active_width >> 1); + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + uint8_t c; + for (int x = this->active_width >> 1; x > 0; x--) { + c = *src_row; + WRITE_DWORD_LE_A(dst_row, this->palette[c >> 4]); + dst_row += 4; + WRITE_DWORD_LE_A(dst_row, this->palette[c & 15]); + dst_row += 4; + src_row += 1; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +void VideoCtrlBase::convert_frame_8bpp_indexed(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + WRITE_DWORD_LE_A(dst_row, this->palette[*src_row++]); + dst_row += 4; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +#if 0 +// alternative version to the above but only works for little endian host +void VideoCtrlBase::convert_frame_8bpp_32LE_indexed(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *dst_row; + uint32_t *src_row; + int src_pitch; + + src_pitch = this->fb_pitch - this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = (uint32_t*)this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width >> 2; x > 0; x--) { + uint32_t pixels = *src_row++; + WRITE_DWORD_LE_A(dst_row , this->palette[(uint8_t)(pixels )]); + WRITE_DWORD_LE_A(dst_row + 4, this->palette[(uint8_t)(pixels >> 8)]); + WRITE_DWORD_LE_A(dst_row + 8, this->palette[(uint8_t)(pixels >> 16)]); + WRITE_DWORD_LE_A(dst_row + 12, this->palette[(uint8_t)(pixels >> 24)]); + dst_row += 16; + } + src_row = (uint32_t*)((uint8_t*)src_row + src_pitch); + dst_row += dst_pitch; + } +} +#endif + +// RGB332 +void VideoCtrlBase::convert_frame_8bpp(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = *src_row++; + uint32_t r = ((c << 16) & 0x00E00000) | ((c << 13) & 0x001C0000) | ((c << 10) & 0x00030000); + uint32_t g = ((c << 11) & 0x0000E000) | ((c << 8) & 0x00001C00) | ((c << 5) & 0x00000300); + uint32_t b = ((c << 6) & 0x000000C0) | ((c << 4) & 0x00000030) | ((c << 2) & 0x0000000C) | (c & 0x00000003); + WRITE_DWORD_LE_A(dst_row, r | g | b); + dst_row += 4; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +// RGB555 +void VideoCtrlBase::convert_frame_15bpp(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - 2 * this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = *((uint16_t*)(src_row)); + uint32_t r = ((c << 9) & 0x00F80000) | ((c << 4) & 0x00070000); + uint32_t g = ((c << 6) & 0x0000F800) | ((c << 1) & 0x00000700); + uint32_t b = ((c << 3) & 0x000000F8) | ((c >> 2) & 0x00000007); + WRITE_DWORD_LE_A(dst_row, r | g | b); + src_row += 2; + dst_row += 4; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +// RGB555_BE +void VideoCtrlBase::convert_frame_15bpp_BE(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - 2 * this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = READ_WORD_BE_A(src_row); + uint32_t r = ((c << 9) & 0x00F80000) | ((c << 4) & 0x00070000); + uint32_t g = ((c << 6) & 0x0000F800) | ((c << 1) & 0x00000700); + uint32_t b = ((c << 3) & 0x000000F8) | ((c >> 2) & 0x00000007); + WRITE_DWORD_LE_A(dst_row, r | g | b); + src_row += 2; + dst_row += 4; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +// RGB565 +void VideoCtrlBase::convert_frame_16bpp(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - 2 * this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = *((uint16_t*)(src_row)); + uint32_t r = ((c << 8) & 0x00F80000) | ((c << 3) & 0x00070000); + uint32_t g = ((c << 5) & 0x0000FC00) | ((c >> 1) & 0x00000300); + uint32_t b = ((c << 3) & 0x000000F8) | ((c >> 2) & 0x00000007); + WRITE_DWORD_LE_A(dst_row, r | g | b); + src_row += 2; + dst_row += 4; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +// RGB888 +void VideoCtrlBase::convert_frame_24bpp(uint8_t *dst_buf, int dst_pitch) +{ + uint8_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - 3 * this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = this->fb_ptr; + dst_row = dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = (src_row[0] << 16) | (src_row[1] << 8) | src_row[2]; + WRITE_DWORD_LE_A(dst_row, c); + src_row += 3; + dst_row += 4; + } + src_row += src_pitch; + dst_row += dst_pitch; + } +} + +// ARGB8888 +void VideoCtrlBase::convert_frame_32bpp(uint8_t *dst_buf, int dst_pitch) +{ + uint32_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - 4 * this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = (uint32_t*)this->fb_ptr; + dst_row = (uint32_t*)dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = READ_DWORD_LE_A(src_row); + WRITE_DWORD_LE_A(dst_row, c); + src_row++; + dst_row++; + } + src_row = (uint32_t*)((uint8_t*)src_row + src_pitch); + dst_row = (uint32_t*)((uint8_t*)dst_row + dst_pitch); + } +} + +// ARGB8888_BE +void VideoCtrlBase::convert_frame_32bpp_BE(uint8_t *dst_buf, int dst_pitch) +{ + uint32_t *src_row, *dst_row; + int src_pitch; + + src_pitch = this->fb_pitch - 4 * this->active_width; + dst_pitch = dst_pitch - 4 * this->active_width; + + src_row = (uint32_t*)this->fb_ptr; + dst_row = (uint32_t*)dst_buf; + for (int h = this->active_height; h > 0; h--) { + for (int x = this->active_width; x > 0; x--) { + uint32_t c = READ_DWORD_BE_A(src_row); + WRITE_DWORD_LE_A(dst_row, c); + src_row++; + dst_row++; + } + src_row = (uint32_t*)((uint8_t*)src_row + src_pitch); + dst_row = (uint32_t*)((uint8_t*)dst_row + dst_pitch); } } diff --git a/devices/video/videoctrl.h b/devices/video/videoctrl.h index 3fd6be7..b047eed 100644 --- a/devices/video/videoctrl.h +++ b/devices/video/videoctrl.h @@ -55,8 +55,20 @@ public: virtual void get_cursor_position(int& x, int& y) { x = 0; y = 0; }; // converters for various framebuffer pixel depths - virtual void convert_frame_1bpp(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_1bpp_indexed(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_2bpp_indexed(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_4bpp_indexed(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_8bpp_indexed(uint8_t *dst_buf, int dst_pitch); +#if 0 + virtual void convert_frame_8bpp_32LE_indexed(uint8_t *dst_buf, int dst_pitch); +#endif virtual void convert_frame_8bpp(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_15bpp(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_15bpp_BE(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_16bpp(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_24bpp(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_32bpp(uint8_t *dst_buf, int dst_pitch); + virtual void convert_frame_32bpp_BE(uint8_t *dst_buf, int dst_pitch); protected: // CRT controller parameters @@ -76,8 +88,8 @@ protected: uint32_t palette[256]; // internal DAC palette in RGBA format // Framebuffer parameters - uint8_t* fb_ptr; - int fb_pitch; + uint8_t* fb_ptr = nullptr; + int fb_pitch = 0; uint32_t refresh_task_id = 0; uint32_t vbl_end_task_id = 0;