sample for qemu: -device virtio-vga,edid=on,xres=1024,yres=768 -display sdl display mode can be set in the Screen preferences. Change-Id: If1d6aeecb208ce7c62c42eea1a95c71237c4375a Reviewed-on: https://review.haiku-os.org/c/haiku/+/7038 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Jérôme Duval <[email protected]>
185 lines
4.4 KiB
C++
185 lines
4.4 KiB
C++
/*
|
|
* Copyright 2005-2015, Axel Dörfler, [email protected].
|
|
* Copyright 2016, Jessica Hamilton, [email protected].
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <compute_display_timing.h>
|
|
#include <create_display_modes.h>
|
|
|
|
#include "accelerant_protos.h"
|
|
#include "accelerant.h"
|
|
|
|
|
|
#define TRACE_MODE
|
|
#ifdef TRACE_MODE
|
|
extern "C" void _sPrintf(const char* format, ...);
|
|
# define TRACE(x) _sPrintf x
|
|
#else
|
|
# define TRACE(x) ;
|
|
#endif
|
|
|
|
|
|
bool
|
|
operator==(const display_mode &lhs, const display_mode &rhs)
|
|
{
|
|
return lhs.space == rhs.space
|
|
&& lhs.virtual_width == rhs.virtual_width
|
|
&& lhs.virtual_height == rhs.virtual_height
|
|
&& lhs.h_display_start == rhs.h_display_start
|
|
&& lhs.v_display_start == rhs.v_display_start;
|
|
}
|
|
|
|
|
|
/*! Checks if the specified \a mode can be set using VESA. */
|
|
static bool
|
|
is_mode_supported(display_mode* mode)
|
|
{
|
|
return (mode != NULL) && (*mode == gInfo->shared_info->current_mode);
|
|
}
|
|
|
|
|
|
/*! Creates the initial mode list of the primary accelerant.
|
|
It's called from vesa_init_accelerant().
|
|
*/
|
|
status_t
|
|
create_mode_list(void)
|
|
{
|
|
const color_space colorspace[] = {
|
|
(color_space)gInfo->shared_info->current_mode.space
|
|
};
|
|
|
|
if (!gInfo->shared_info->has_edid) {
|
|
display_mode mode = gInfo->shared_info->current_mode;
|
|
|
|
compute_display_timing(mode.virtual_width, mode.virtual_height, 60, false,
|
|
&mode.timing);
|
|
fill_display_mode(mode.virtual_width, mode.virtual_height, &mode);
|
|
|
|
gInfo->mode_list_area = create_display_modes("virtio_gpu modes",
|
|
NULL, &mode, 1, colorspace, 1, is_mode_supported, &gInfo->mode_list,
|
|
&gInfo->shared_info->mode_count);
|
|
} else {
|
|
edid1_info edidInfo;
|
|
edid_decode(&edidInfo, &gInfo->shared_info->edid_raw);
|
|
gInfo->mode_list_area = create_display_modes("virtio_gpu modes",
|
|
&edidInfo, NULL, 0, colorspace, 1, NULL, &gInfo->mode_list,
|
|
&gInfo->shared_info->mode_count);
|
|
}
|
|
if (gInfo->mode_list_area < 0)
|
|
return gInfo->mode_list_area;
|
|
|
|
gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
uint32
|
|
virtio_gpu_accelerant_mode_count(void)
|
|
{
|
|
TRACE(("virtio_gpu_accelerant_mode_count() = %d\n",
|
|
gInfo->shared_info->mode_count));
|
|
return gInfo->shared_info->mode_count;
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_get_mode_list(display_mode* modeList)
|
|
{
|
|
TRACE(("virtio_gpu_get_mode_info()\n"));
|
|
memcpy(modeList, gInfo->mode_list,
|
|
gInfo->shared_info->mode_count * sizeof(display_mode));
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_get_preferred_mode(display_mode* _mode)
|
|
{
|
|
TRACE(("virtio_gpu_get_preferred_mode()\n"));
|
|
*_mode = gInfo->shared_info->current_mode;
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_set_display_mode(display_mode* _mode)
|
|
{
|
|
TRACE(("virtio_gpu_set_display_mode()\n"));
|
|
if (_mode != NULL && *_mode == gInfo->shared_info->current_mode)
|
|
return B_OK;
|
|
|
|
return ioctl(gInfo->device, VIRTIO_GPU_SET_DISPLAY_MODE,
|
|
_mode, sizeof(display_mode));
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_get_display_mode(display_mode* _currentMode)
|
|
{
|
|
TRACE(("virtio_gpu_get_display_mode()\n"));
|
|
*_currentMode = gInfo->shared_info->current_mode;
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_get_edid_info(void* info, size_t size, uint32* _version)
|
|
{
|
|
TRACE(("virtio_gpu_get_edid_info()\n"));
|
|
|
|
if (!gInfo->shared_info->has_edid)
|
|
return B_ERROR;
|
|
if (size < sizeof(struct edid1_info))
|
|
return B_BUFFER_OVERFLOW;
|
|
|
|
edid_decode((edid1_info*)info, &gInfo->shared_info->edid_raw);
|
|
*_version = EDID_VERSION_1;
|
|
edid_dump((edid1_info*)info);
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_get_frame_buffer_config(frame_buffer_config* config)
|
|
{
|
|
TRACE(("virtio_gpu_get_frame_buffer_config()\n"));
|
|
|
|
config->frame_buffer = gInfo->shared_info->frame_buffer;
|
|
TRACE(("virtio_gpu_get_frame_buffer_config() = %" B_PRIxADDR "\n",
|
|
config->frame_buffer));
|
|
//config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
|
|
config->bytes_per_row = gInfo->shared_info->bytes_per_row;
|
|
TRACE(("virtio_gpu_get_frame_buffer_config() %p\n", config->frame_buffer));
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
virtio_gpu_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high)
|
|
{
|
|
TRACE(("virtio_gpu_get_pixel_clock_limits()\n"));
|
|
|
|
// TODO: do some real stuff here (taken from radeon driver)
|
|
uint32 totalPixel = (uint32)mode->timing.h_total
|
|
* (uint32)mode->timing.v_total;
|
|
uint32 clockLimit = 2000000;
|
|
|
|
// lower limit of about 48Hz vertical refresh
|
|
*_low = totalPixel * 48L / 1000L;
|
|
if (*_low > clockLimit)
|
|
return B_ERROR;
|
|
|
|
*_high = clockLimit;
|
|
return B_OK;
|
|
}
|
|
|