videoctrl: support guest rendered HW cursors.

This commit is contained in:
Maxim Poliakovski 2023-04-02 01:56:24 +02:00
parent 74a49d1568
commit 616d0728fd
4 changed files with 63 additions and 12 deletions

View File

@ -351,7 +351,10 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
return;
case ATI_GEN_TEST_CNTL:
if (bit_changed(this->regs[reg_offset >> 2], value, 7)) {
LOG_F(INFO, "%s: HW cursor status changed", this->name.c_str());
if (bit_set(value, 7))
this->setup_hw_cursor();
else
this->cursor_on = false;
}
if (bit_changed(this->regs[reg_offset >> 2], value, 8)) {
if (!bit_set(value, 8))
@ -606,6 +609,7 @@ void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
WRITE_DWORD_BE_A(dst_row, color1);
break;
case 2: // transparent
WRITE_DWORD_BE_A(dst_row, 0);
break;
case 3: // 1's complement of display pixel
break;
@ -615,6 +619,11 @@ void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {
}
}
void ATIRage::get_cursor_position(int& x, int& y) {
x = this->regs[ATI_CUR_HORZ_VERT_POSN >> 2] & 0xFFFFU;
y = (this->regs[ATI_CUR_HORZ_VERT_POSN >> 2] >> 16) & 0xFFFFU;
}
static const PropMap AtiRage_Properties = {
{"gfxmem_size",
new IntProperty( 2, vector<uint32_t>({2, 4, 6}))},

View File

@ -78,6 +78,7 @@ protected:
void crtc_update();
void crtc_enable();
void draw_hw_cursor(uint8_t *dst_buf, int dst_pitch);
void get_cursor_position(int& x, int& y);
private:
uint32_t regs[512] = {}; // internal registers

View File

@ -45,6 +45,10 @@ VideoCtrlBase::VideoCtrlBase(int width, int height)
VideoCtrlBase::~VideoCtrlBase()
{
if (this->cursor_texture) {
SDL_DestroyTexture(this->cursor_texture);
}
if (this->disp_texture) {
SDL_DestroyTexture(this->disp_texture);
}
@ -136,18 +140,14 @@ void VideoCtrlBase::update_screen()
SDL_UnlockTexture(this->disp_texture);
SDL_RenderClear(this->renderer);
SDL_RenderCopy(this->renderer, this->disp_texture, NULL, NULL);
// draw HW cursor if enabled
if (this->cursor_on) {
this->get_cursor_position(cursor_rect.x, cursor_rect.y);
SDL_RenderCopy(this->renderer, this->cursor_texture, NULL, &cursor_rect);
}
SDL_RenderPresent(this->renderer);
// HW cursor data is stored at the beginning of the video memory
// HACK: use src_offset to recognize cursor data being ready
// Normally, we should check GEN_CUR_ENABLE bit in the GEN_TEST_CNTL register
//if (src_offset > 0x400 && READ_DWORD_LE_A(&this->block_io_regs[ATI_CUR_OFFSET])) {
// this->draw_hw_cursor(dst_buf + dst_pitch * 20 + 120, dst_pitch);
//}
//auto end_time = std::chrono::steady_clock::now();
//auto time_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
//LOG_F(INFO, "Display uodate took: %lld ns", time_elapsed.count());
}
void VideoCtrlBase::get_palette_colors(uint8_t index, uint8_t& r, uint8_t& g,
@ -164,6 +164,39 @@ void VideoCtrlBase::set_palette_color(uint8_t index, uint8_t r, uint8_t g, uint8
this->palette[index] = (a << 24) | (r << 16) | (g << 8) | b;
}
void VideoCtrlBase::setup_hw_cursor(int cursor_width, int cursor_height)
{
uint8_t* dst_buf;
int dst_pitch;
if (this->cursor_texture) {
SDL_DestroyTexture(this->cursor_texture);
}
this->cursor_texture = SDL_CreateTexture(
this->renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
cursor_width, cursor_height
);
if (this->cursor_texture == NULL) {
ABORT_F("SDL_CreateTexture for HW cursor failed with %s", SDL_GetError());
}
SDL_LockTexture(this->cursor_texture, NULL, (void **)&dst_buf, &dst_pitch);
SDL_SetTextureBlendMode(this->cursor_texture, SDL_BLENDMODE_BLEND);
this->draw_hw_cursor(dst_buf, dst_pitch);
SDL_UnlockTexture(this->cursor_texture);
this->cursor_rect.x = 0;
this->cursor_rect.y = 0;
this->cursor_rect.w = cursor_width;
this->cursor_rect.h = cursor_height;
this->cursor_on = true;
}
void VideoCtrlBase::convert_frame_1bpp(uint8_t *dst_buf, int dst_pitch)
{
// TODO: implement me!

View File

@ -42,6 +42,11 @@ public:
uint8_t& a);
void set_palette_color(uint8_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
// HW cursor support
void setup_hw_cursor(int cursor_width=64, int cur_height=64);
virtual void draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) {};
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_8bpp(uint8_t *dst_buf, int dst_pitch);
@ -51,6 +56,7 @@ protected:
bool crtc_on = false;
bool blank_on = true;
bool resizing = false;
bool cursor_on = false;
int active_width; // width of the visible display area
int active_height; // height of the visible display area
int hori_total = 0;
@ -73,6 +79,8 @@ private:
SDL_Window* display_wnd = 0;
SDL_Renderer* renderer = 0;
SDL_Texture* disp_texture = 0;
SDL_Texture* cursor_texture = 0;
SDL_Rect cursor_rect; // destination rectangle for cursor drawing
};
#endif // VIDEO_CTRL_H