mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 15:30:14 +01:00
st/egl: update fbdev backend
Considering fbdev as an in-kernel window system, - opening a device opens a connection - there is only one window: the framebuffer - fb_var_screeninfo decides window position, size, and even color format - there is no pixmap Now EGL is built on top of this window system. So we should have - the fd as the handle of the native display - reject all but one native window: NULL - no pixmap support modeset support is still around, but it should be removed soon.
This commit is contained in:
parent
a2537bbc95
commit
aa281dd392
3 changed files with 242 additions and 174 deletions
|
|
@ -26,6 +26,21 @@
|
||||||
* Chia-I Wu <olv@lunarg.com>
|
* Chia-I Wu <olv@lunarg.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Considering fbdev as an in-kernel window system,
|
||||||
|
*
|
||||||
|
* - opening a device opens a connection
|
||||||
|
* - there is only one window: the framebuffer
|
||||||
|
* - fb_var_screeninfo decides window position, size, and even color format
|
||||||
|
* - there is no pixmap
|
||||||
|
*
|
||||||
|
* Now EGL is built on top of this window system. So we should have
|
||||||
|
*
|
||||||
|
* - the fd as the handle of the native display
|
||||||
|
* - reject all but one native window: NULL
|
||||||
|
* - no pixmap support
|
||||||
|
*/
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -48,13 +63,10 @@ struct fbdev_display {
|
||||||
const struct native_event_handler *event_handler;
|
const struct native_event_handler *event_handler;
|
||||||
|
|
||||||
struct fb_fix_screeninfo finfo;
|
struct fb_fix_screeninfo finfo;
|
||||||
struct fb_var_screeninfo vinfo;
|
struct fb_var_screeninfo config_vinfo;
|
||||||
|
|
||||||
struct native_config config;
|
struct native_config config;
|
||||||
struct native_connector connector;
|
|
||||||
struct native_mode mode;
|
|
||||||
|
|
||||||
struct fbdev_surface *current_surface;
|
boolean assume_fixed_vinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fbdev_surface {
|
struct fbdev_surface {
|
||||||
|
|
@ -66,7 +78,7 @@ struct fbdev_surface {
|
||||||
|
|
||||||
unsigned int sequence_number;
|
unsigned int sequence_number;
|
||||||
|
|
||||||
boolean is_current;
|
struct fbdev_sw_drawable drawable;
|
||||||
};
|
};
|
||||||
|
|
||||||
static INLINE struct fbdev_display *
|
static INLINE struct fbdev_display *
|
||||||
|
|
@ -103,38 +115,70 @@ fbdev_surface_validate(struct native_surface *nsurf, uint attachment_mask,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
static enum pipe_format
|
||||||
fbdev_surface_flush_frontbuffer(struct native_surface *nsurf)
|
vinfo_to_format(const struct fb_var_screeninfo *vinfo)
|
||||||
{
|
{
|
||||||
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
|
enum pipe_format format = PIPE_FORMAT_NONE;
|
||||||
|
|
||||||
if (!fbsurf->is_current)
|
/* should also check channel offsets... */
|
||||||
return TRUE;
|
switch (vinfo->bits_per_pixel) {
|
||||||
|
case 32:
|
||||||
|
if (vinfo->red.length == 8 &&
|
||||||
|
vinfo->green.length == 8 &&
|
||||||
|
vinfo->blue.length == 8) {
|
||||||
|
format = (vinfo->transp.length == 8) ?
|
||||||
|
PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
if (vinfo->red.length == 5 &&
|
||||||
|
vinfo->green.length == 6 &&
|
||||||
|
vinfo->blue.length == 5 &&
|
||||||
|
vinfo->transp.length == 0)
|
||||||
|
format = PIPE_FORMAT_B5G6R5_UNORM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return resource_surface_present(fbsurf->rsurf,
|
return format;
|
||||||
NATIVE_ATTACHMENT_FRONT_LEFT, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
fbdev_surface_swap_buffers(struct native_surface *nsurf)
|
fbdev_surface_update_drawable(struct native_surface *nsurf,
|
||||||
|
const struct fb_var_screeninfo *vinfo)
|
||||||
{
|
{
|
||||||
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
|
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
|
||||||
struct fbdev_display *fbdpy = fbsurf->fbdpy;
|
unsigned x, y, width, height;
|
||||||
boolean ret = TRUE;
|
|
||||||
|
|
||||||
if (fbsurf->is_current) {
|
x = vinfo->xoffset;
|
||||||
ret = resource_surface_present(fbsurf->rsurf,
|
y = vinfo->yoffset;
|
||||||
NATIVE_ATTACHMENT_BACK_LEFT, NULL);
|
width = MIN2(vinfo->xres, fbsurf->width);
|
||||||
|
height = MIN2(vinfo->yres, fbsurf->height);
|
||||||
|
|
||||||
|
/* sanitize the values */
|
||||||
|
if (x + width > vinfo->xres_virtual) {
|
||||||
|
if (x > vinfo->xres_virtual)
|
||||||
|
width = 0;
|
||||||
|
else
|
||||||
|
width = vinfo->xres_virtual - x;
|
||||||
|
}
|
||||||
|
if (y + height > vinfo->yres_virtual) {
|
||||||
|
if (y > vinfo->yres_virtual)
|
||||||
|
height = 0;
|
||||||
|
else
|
||||||
|
height = vinfo->yres_virtual - y;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource_surface_swap_buffers(fbsurf->rsurf,
|
fbsurf->drawable.format = vinfo_to_format(vinfo);
|
||||||
NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE);
|
fbsurf->drawable.x = vinfo->xoffset;
|
||||||
/* the front/back textures are swapped */
|
fbsurf->drawable.y = vinfo->yoffset;
|
||||||
fbsurf->sequence_number++;
|
fbsurf->drawable.width = vinfo->xres;
|
||||||
fbdpy->event_handler->invalid_surface(&fbdpy->base,
|
fbsurf->drawable.height = vinfo->yres;
|
||||||
&fbsurf->base, fbsurf->sequence_number);
|
|
||||||
|
|
||||||
return ret;
|
return (fbsurf->drawable.format != PIPE_FORMAT_NONE &&
|
||||||
|
fbsurf->drawable.width &&
|
||||||
|
fbsurf->drawable.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
|
|
@ -143,21 +187,43 @@ fbdev_surface_present(struct native_surface *nsurf,
|
||||||
boolean preserve,
|
boolean preserve,
|
||||||
uint swap_interval)
|
uint swap_interval)
|
||||||
{
|
{
|
||||||
boolean ret;
|
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
|
||||||
|
struct fbdev_display *fbdpy = fbsurf->fbdpy;
|
||||||
|
boolean ret = FALSE;
|
||||||
|
|
||||||
if (preserve || swap_interval)
|
if (swap_interval)
|
||||||
|
return FALSE;
|
||||||
|
if (natt != NATIVE_ATTACHMENT_BACK_LEFT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
switch (natt) {
|
if (!fbdpy->assume_fixed_vinfo) {
|
||||||
case NATIVE_ATTACHMENT_FRONT_LEFT:
|
struct fb_var_screeninfo vinfo;
|
||||||
ret = fbdev_surface_flush_frontbuffer(nsurf);
|
|
||||||
break;
|
memset(&vinfo, 0, sizeof(vinfo));
|
||||||
case NATIVE_ATTACHMENT_BACK_LEFT:
|
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo))
|
||||||
ret = fbdev_surface_swap_buffers(nsurf);
|
return FALSE;
|
||||||
break;
|
|
||||||
default:
|
/* present the surface */
|
||||||
ret = FALSE;
|
if (fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) {
|
||||||
break;
|
ret = resource_surface_present(fbsurf->rsurf,
|
||||||
|
natt, (void *) &fbsurf->drawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
fbsurf->width = vinfo.xres;
|
||||||
|
fbsurf->height = vinfo.yres;
|
||||||
|
|
||||||
|
if (resource_surface_set_size(fbsurf->rsurf,
|
||||||
|
fbsurf->width, fbsurf->height)) {
|
||||||
|
/* surface resized */
|
||||||
|
fbsurf->sequence_number++;
|
||||||
|
fbdpy->event_handler->invalid_surface(&fbdpy->base,
|
||||||
|
&fbsurf->base, fbsurf->sequence_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* the drawable never changes */
|
||||||
|
ret = resource_surface_present(fbsurf->rsurf,
|
||||||
|
natt, (void *) &fbsurf->drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -179,26 +245,48 @@ fbdev_surface_destroy(struct native_surface *nsurf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct native_surface *
|
static struct native_surface *
|
||||||
fbdev_display_create_scanout_surface(struct native_display *ndpy,
|
fbdev_display_create_window_surface(struct native_display *ndpy,
|
||||||
const struct native_config *nconf,
|
EGLNativeWindowType win,
|
||||||
uint width, uint height)
|
const struct native_config *nconf)
|
||||||
{
|
{
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
||||||
struct fbdev_surface *fbsurf;
|
struct fbdev_surface *fbsurf;
|
||||||
|
struct fb_var_screeninfo vinfo;
|
||||||
|
|
||||||
|
/* there is only one native window: NULL */
|
||||||
|
if (win)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
fbsurf = CALLOC_STRUCT(fbdev_surface);
|
fbsurf = CALLOC_STRUCT(fbdev_surface);
|
||||||
if (!fbsurf)
|
if (!fbsurf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fbsurf->fbdpy = fbdpy;
|
fbsurf->fbdpy = fbdpy;
|
||||||
fbsurf->width = width;
|
|
||||||
fbsurf->height = height;
|
/* get current vinfo */
|
||||||
|
if (fbdpy->assume_fixed_vinfo) {
|
||||||
|
vinfo = fbdpy->config_vinfo;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(&vinfo, 0, sizeof(vinfo));
|
||||||
|
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo)) {
|
||||||
|
FREE(fbsurf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fbsurf->width = vinfo.xres;
|
||||||
|
fbsurf->height = vinfo.yres;
|
||||||
|
|
||||||
|
if (!fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) {
|
||||||
|
FREE(fbsurf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
fbsurf->rsurf = resource_surface_create(fbdpy->base.screen,
|
fbsurf->rsurf = resource_surface_create(fbdpy->base.screen,
|
||||||
nconf->color_format,
|
nconf->color_format,
|
||||||
PIPE_BIND_RENDER_TARGET |
|
PIPE_BIND_RENDER_TARGET |
|
||||||
PIPE_BIND_DISPLAY_TARGET |
|
PIPE_BIND_DISPLAY_TARGET);
|
||||||
PIPE_BIND_SCANOUT);
|
|
||||||
if (!fbsurf->rsurf) {
|
if (!fbsurf->rsurf) {
|
||||||
FREE(fbsurf);
|
FREE(fbsurf);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -214,42 +302,43 @@ fbdev_display_create_scanout_surface(struct native_display *ndpy,
|
||||||
return &fbsurf->base;
|
return &fbsurf->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct native_surface *
|
||||||
|
fbdev_display_create_scanout_surface(struct native_display *ndpy,
|
||||||
|
const struct native_config *nconf,
|
||||||
|
uint width, uint height)
|
||||||
|
{
|
||||||
|
return fbdev_display_create_window_surface(ndpy,
|
||||||
|
(EGLNativeWindowType) NULL, nconf);
|
||||||
|
}
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
fbdev_display_program(struct native_display *ndpy, int crtc_idx,
|
fbdev_display_program(struct native_display *ndpy, int crtc_idx,
|
||||||
struct native_surface *nsurf, uint x, uint y,
|
struct native_surface *nsurf, uint x, uint y,
|
||||||
const struct native_connector **nconns, int num_nconns,
|
const struct native_connector **nconns, int num_nconns,
|
||||||
const struct native_mode *nmode)
|
const struct native_mode *nmode)
|
||||||
{
|
{
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
|
||||||
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
|
|
||||||
|
|
||||||
if (x || y)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (fbdpy->current_surface) {
|
|
||||||
if (fbdpy->current_surface == fbsurf)
|
|
||||||
return TRUE;
|
|
||||||
fbdpy->current_surface->is_current = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fbsurf)
|
|
||||||
fbsurf->is_current = TRUE;
|
|
||||||
fbdpy->current_surface = fbsurf;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct native_mode **
|
static const struct native_mode **
|
||||||
fbdev_display_get_modes(struct native_display *ndpy,
|
fbdev_display_get_modes(struct native_display *ndpy,
|
||||||
const struct native_connector *nconn,
|
const struct native_connector *nconn,
|
||||||
int *num_modes)
|
int *num_modes)
|
||||||
{
|
{
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
static struct native_mode mode;
|
||||||
const struct native_mode **modes;
|
const struct native_mode **modes;
|
||||||
|
|
||||||
|
if (!mode.desc) {
|
||||||
|
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
||||||
|
mode.desc = "Current Mode";
|
||||||
|
mode.width = fbdpy->config_vinfo.xres;
|
||||||
|
mode.height = fbdpy->config_vinfo.yres;
|
||||||
|
mode.refresh_rate = 60 * 1000; /* dummy */
|
||||||
|
}
|
||||||
|
|
||||||
modes = MALLOC(sizeof(*modes));
|
modes = MALLOC(sizeof(*modes));
|
||||||
if (modes) {
|
if (modes) {
|
||||||
modes[0] = &fbdpy->mode;
|
modes[0] = &mode;
|
||||||
if (num_modes)
|
if (num_modes)
|
||||||
*num_modes = 1;
|
*num_modes = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -261,12 +350,12 @@ static const struct native_connector **
|
||||||
fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors,
|
fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors,
|
||||||
int *num_crtc)
|
int *num_crtc)
|
||||||
{
|
{
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
static struct native_connector connector;
|
||||||
const struct native_connector **connectors;
|
const struct native_connector **connectors;
|
||||||
|
|
||||||
connectors = MALLOC(sizeof(*connectors));
|
connectors = MALLOC(sizeof(*connectors));
|
||||||
if (connectors) {
|
if (connectors) {
|
||||||
connectors[0] = &fbdpy->connector;
|
connectors[0] = &connector;
|
||||||
if (num_connectors)
|
if (num_connectors)
|
||||||
*num_connectors = 1;
|
*num_connectors = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +363,8 @@ fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors,
|
||||||
return connectors;
|
return connectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct native_display_modeset fbdev_display_modeset = {
|
/* remove modeset support one day! */
|
||||||
|
static const struct native_display_modeset fbdev_display_modeset = {
|
||||||
.get_connectors = fbdev_display_get_connectors,
|
.get_connectors = fbdev_display_get_connectors,
|
||||||
.get_modes = fbdev_display_get_modes,
|
.get_modes = fbdev_display_get_modes,
|
||||||
.create_scanout_surface = fbdev_display_create_scanout_surface,
|
.create_scanout_surface = fbdev_display_create_scanout_surface,
|
||||||
|
|
@ -304,8 +394,10 @@ fbdev_display_get_param(struct native_display *ndpy,
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case NATIVE_PARAM_USE_NATIVE_BUFFER:
|
|
||||||
case NATIVE_PARAM_PRESERVE_BUFFER:
|
case NATIVE_PARAM_PRESERVE_BUFFER:
|
||||||
|
val = 1;
|
||||||
|
break;
|
||||||
|
case NATIVE_PARAM_USE_NATIVE_BUFFER:
|
||||||
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
|
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
|
||||||
default:
|
default:
|
||||||
val = 0;
|
val = 0;
|
||||||
|
|
@ -325,80 +417,13 @@ fbdev_display_destroy(struct native_display *ndpy)
|
||||||
FREE(fbdpy);
|
FREE(fbdpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
|
||||||
fbdev_display_init_modes(struct native_display *ndpy)
|
|
||||||
{
|
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
|
||||||
struct native_mode *nmode = &fbdpy->mode;
|
|
||||||
|
|
||||||
nmode->desc = "Current Mode";
|
|
||||||
nmode->width = fbdpy->vinfo.xres;
|
|
||||||
nmode->height = fbdpy->vinfo.yres;
|
|
||||||
nmode->refresh_rate = 60 * 1000; /* dummy */
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean
|
|
||||||
fbdev_display_init_connectors(struct native_display *ndpy)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum pipe_format
|
|
||||||
vinfo_to_format(const struct fb_var_screeninfo *vinfo)
|
|
||||||
{
|
|
||||||
enum pipe_format format = PIPE_FORMAT_NONE;
|
|
||||||
|
|
||||||
switch (vinfo->bits_per_pixel) {
|
|
||||||
case 32:
|
|
||||||
if (vinfo->red.length == 8 &&
|
|
||||||
vinfo->green.length == 8 &&
|
|
||||||
vinfo->blue.length == 8) {
|
|
||||||
format = (vinfo->transp.length == 8) ?
|
|
||||||
PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
if (vinfo->red.length == 5 &&
|
|
||||||
vinfo->green.length == 6 &&
|
|
||||||
vinfo->blue.length == 5 &&
|
|
||||||
vinfo->transp.length == 0)
|
|
||||||
format = PIPE_FORMAT_B5G6R5_UNORM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean
|
|
||||||
fbdev_display_init_configs(struct native_display *ndpy)
|
|
||||||
{
|
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
|
||||||
struct native_config *nconf = &fbdpy->config;
|
|
||||||
|
|
||||||
nconf->color_format = vinfo_to_format(&fbdpy->vinfo);
|
|
||||||
if (nconf->color_format == PIPE_FORMAT_NONE)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
nconf->buffer_mask =
|
|
||||||
(1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
|
|
||||||
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
|
|
||||||
|
|
||||||
nconf->scanout_bit = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
fbdev_display_init_screen(struct native_display *ndpy)
|
fbdev_display_init_screen(struct native_display *ndpy)
|
||||||
{
|
{
|
||||||
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
||||||
struct sw_winsys *ws;
|
struct sw_winsys *ws;
|
||||||
|
|
||||||
ws = fbdev_create_sw_winsys(fbdpy->fd, fbdpy->config.color_format);
|
ws = fbdev_create_sw_winsys(fbdpy->fd);
|
||||||
if (!ws)
|
if (!ws)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -420,6 +445,26 @@ fbdev_display_init_screen(struct native_display *ndpy)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
fbdev_display_init_config(struct native_display *ndpy)
|
||||||
|
{
|
||||||
|
struct fbdev_display *fbdpy = fbdev_display(ndpy);
|
||||||
|
struct native_config *nconf = &fbdpy->config;
|
||||||
|
|
||||||
|
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->config_vinfo))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
nconf->color_format = vinfo_to_format(&fbdpy->config_vinfo);
|
||||||
|
if (nconf->color_format == PIPE_FORMAT_NONE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
nconf->buffer_mask = (1 << NATIVE_ATTACHMENT_BACK_LEFT);
|
||||||
|
|
||||||
|
nconf->window_bit = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static struct native_display *
|
static struct native_display *
|
||||||
fbdev_display_create(int fd, const struct native_event_handler *event_handler)
|
fbdev_display_create(int fd, const struct native_event_handler *event_handler)
|
||||||
{
|
{
|
||||||
|
|
@ -435,23 +480,24 @@ fbdev_display_create(int fd, const struct native_event_handler *event_handler)
|
||||||
if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo))
|
if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->vinfo))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR ||
|
if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR ||
|
||||||
fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS)
|
fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!fbdev_display_init_configs(&fbdpy->base) ||
|
if (!fbdev_display_init_config(&fbdpy->base))
|
||||||
!fbdev_display_init_connectors(&fbdpy->base) ||
|
|
||||||
!fbdev_display_init_modes(&fbdpy->base))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
fbdpy->assume_fixed_vinfo = TRUE;
|
||||||
|
|
||||||
fbdpy->base.init_screen = fbdev_display_init_screen;
|
fbdpy->base.init_screen = fbdev_display_init_screen;
|
||||||
fbdpy->base.destroy = fbdev_display_destroy;
|
fbdpy->base.destroy = fbdev_display_destroy;
|
||||||
fbdpy->base.get_param = fbdev_display_get_param;
|
fbdpy->base.get_param = fbdev_display_get_param;
|
||||||
fbdpy->base.get_configs = fbdev_display_get_configs;
|
fbdpy->base.get_configs = fbdev_display_get_configs;
|
||||||
|
|
||||||
|
fbdpy->base.create_window_surface = fbdev_display_create_window_surface;
|
||||||
|
|
||||||
|
/* we'd like to remove modeset support one day */
|
||||||
|
fbdpy->config.scanout_bit = TRUE;
|
||||||
fbdpy->base.modeset = &fbdev_display_modeset;
|
fbdpy->base.modeset = &fbdev_display_modeset;
|
||||||
|
|
||||||
return &fbdpy->base;
|
return &fbdpy->base;
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,8 @@ struct fbdev_sw_winsys
|
||||||
struct sw_winsys base;
|
struct sw_winsys base;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
enum pipe_format format;
|
|
||||||
|
|
||||||
struct fb_fix_screeninfo finfo;
|
struct fb_fix_screeninfo finfo;
|
||||||
void *fbmem;
|
|
||||||
unsigned rows;
|
unsigned rows;
|
||||||
unsigned stride;
|
unsigned stride;
|
||||||
};
|
};
|
||||||
|
|
@ -77,22 +75,53 @@ fbdev_sw_winsys(struct sw_winsys *ws)
|
||||||
static void
|
static void
|
||||||
fbdev_displaytarget_display(struct sw_winsys *ws,
|
fbdev_displaytarget_display(struct sw_winsys *ws,
|
||||||
struct sw_displaytarget *dt,
|
struct sw_displaytarget *dt,
|
||||||
void *context_private)
|
void *winsys_private)
|
||||||
{
|
{
|
||||||
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
|
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
|
||||||
struct fbdev_sw_displaytarget *fbdt = fbdev_sw_displaytarget(dt);
|
struct fbdev_sw_displaytarget *src = fbdev_sw_displaytarget(dt);
|
||||||
unsigned rows, len, i;
|
const struct fbdev_sw_drawable *dst =
|
||||||
|
(const struct fbdev_sw_drawable *) winsys_private;
|
||||||
|
unsigned height, row_offset, row_len, i;
|
||||||
|
void *fbmem;
|
||||||
|
|
||||||
rows = MIN2(fbdt->height, fbdev->rows);
|
/* FIXME format conversion */
|
||||||
len = util_format_get_stride(fbdt->format, fbdt->width);
|
if (dst->format != src->format) {
|
||||||
len = MIN2(len, fbdev->stride);
|
assert(0);
|
||||||
|
return;
|
||||||
for (i = 0; i < rows; i++) {
|
|
||||||
void *dst = fbdev->fbmem + fbdev->stride * i;
|
|
||||||
void *src = fbdt->data + fbdt->stride * i;
|
|
||||||
|
|
||||||
memcpy(dst, src, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
height = dst->height;
|
||||||
|
if (dst->y + dst->height > fbdev->rows) {
|
||||||
|
/* nothing to copy */
|
||||||
|
if (dst->y >= fbdev->rows)
|
||||||
|
return;
|
||||||
|
|
||||||
|
height = fbdev->rows - dst->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
row_offset = util_format_get_stride(dst->format, dst->x);
|
||||||
|
row_len = util_format_get_stride(dst->format, dst->width);
|
||||||
|
if (row_offset + row_len > fbdev->stride) {
|
||||||
|
/* nothing to copy */
|
||||||
|
if (row_offset >= fbdev->stride)
|
||||||
|
return;
|
||||||
|
|
||||||
|
row_len = fbdev->stride - row_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fbmem = mmap(0, fbdev->finfo.smem_len,
|
||||||
|
PROT_WRITE, MAP_SHARED, fbdev->fd, 0);
|
||||||
|
if (fbmem == MAP_FAILED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
char *from = (char *) src->data + src->stride * i;
|
||||||
|
char *to = (char *) fbmem + fbdev->stride * (dst->y + i) + row_offset;
|
||||||
|
|
||||||
|
memcpy(to, from, row_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(fbmem, fbdev->finfo.smem_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -133,13 +162,9 @@ fbdev_displaytarget_create(struct sw_winsys *ws,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
unsigned *stride)
|
unsigned *stride)
|
||||||
{
|
{
|
||||||
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
|
|
||||||
struct fbdev_sw_displaytarget *fbdt;
|
struct fbdev_sw_displaytarget *fbdt;
|
||||||
unsigned nblocksy, size, format_stride;
|
unsigned nblocksy, size, format_stride;
|
||||||
|
|
||||||
if (fbdev->format != format)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
fbdt = CALLOC_STRUCT(fbdev_sw_displaytarget);
|
fbdt = CALLOC_STRUCT(fbdev_sw_displaytarget);
|
||||||
if (!fbdt)
|
if (!fbdt)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -170,8 +195,7 @@ fbdev_is_displaytarget_format_supported(struct sw_winsys *ws,
|
||||||
unsigned tex_usage,
|
unsigned tex_usage,
|
||||||
enum pipe_format format)
|
enum pipe_format format)
|
||||||
{
|
{
|
||||||
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
|
return TRUE;
|
||||||
return (fbdev->format == format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -179,12 +203,11 @@ fbdev_destroy(struct sw_winsys *ws)
|
||||||
{
|
{
|
||||||
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
|
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
|
||||||
|
|
||||||
munmap(fbdev->fbmem, fbdev->finfo.smem_len);
|
|
||||||
FREE(fbdev);
|
FREE(fbdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sw_winsys *
|
struct sw_winsys *
|
||||||
fbdev_create_sw_winsys(int fd, enum pipe_format format)
|
fbdev_create_sw_winsys(int fd)
|
||||||
{
|
{
|
||||||
struct fbdev_sw_winsys *fbdev;
|
struct fbdev_sw_winsys *fbdev;
|
||||||
|
|
||||||
|
|
@ -193,19 +216,11 @@ fbdev_create_sw_winsys(int fd, enum pipe_format format)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fbdev->fd = fd;
|
fbdev->fd = fd;
|
||||||
fbdev->format = format;
|
|
||||||
if (ioctl(fbdev->fd, FBIOGET_FSCREENINFO, &fbdev->finfo)) {
|
if (ioctl(fbdev->fd, FBIOGET_FSCREENINFO, &fbdev->finfo)) {
|
||||||
FREE(fbdev);
|
FREE(fbdev);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fbdev->fbmem = mmap(0, fbdev->finfo.smem_len,
|
|
||||||
PROT_WRITE, MAP_SHARED, fbdev->fd, 0);
|
|
||||||
if (fbdev->fbmem == MAP_FAILED) {
|
|
||||||
FREE(fbdev);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fbdev->rows = fbdev->finfo.smem_len / fbdev->finfo.line_length;
|
fbdev->rows = fbdev->finfo.smem_len / fbdev->finfo.line_length;
|
||||||
fbdev->stride = fbdev->finfo.line_length;
|
fbdev->stride = fbdev->finfo.line_length;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,14 @@
|
||||||
struct sw_winsys;
|
struct sw_winsys;
|
||||||
enum pipe_format;
|
enum pipe_format;
|
||||||
|
|
||||||
|
/* for pipe_screen::flush_frontbuffer */
|
||||||
|
struct fbdev_sw_drawable {
|
||||||
|
enum pipe_format format;
|
||||||
|
unsigned x, y;
|
||||||
|
unsigned width, height;
|
||||||
|
};
|
||||||
|
|
||||||
struct sw_winsys *
|
struct sw_winsys *
|
||||||
fbdev_create_sw_winsys(int fd, enum pipe_format format);
|
fbdev_create_sw_winsys(int fd);
|
||||||
|
|
||||||
#endif /* FBDEV_SW_WINSYS */
|
#endif /* FBDEV_SW_WINSYS */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue