2
* Mesa 3-D graphics library
5
* Copyright (C) 2010 LunarG Inc.
7
* Permission is hereby granted, free of charge, to any person obtaining a
8
* copy of this software and associated documentation files (the "Software"),
9
* to deal in the Software without restriction, including without limitation
10
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
* and/or sell copies of the Software, and to permit persons to whom the
12
* Software is furnished to do so, subject to the following conditions:
14
* The above copyright notice and this permission notice shall be included
15
* in all copies or substantial portions of the Software.
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
* DEALINGS IN THE SOFTWARE.
26
* Chia-I Wu <olv@lunarg.com>
29
#include <sys/ioctl.h>
30
#include <sys/types.h>
35
#include "pipe/p_screen.h"
36
#include "util/u_memory.h"
37
#include "util/u_inlines.h"
38
#include "util/u_pointer.h"
40
#include "common/native.h"
41
#include "common/native_helper.h"
42
#include "fbdev/fbdev_sw_winsys.h"
44
struct fbdev_display {
45
struct native_display base;
48
struct native_event_handler *event_handler;
50
struct fb_fix_screeninfo finfo;
51
struct fb_var_screeninfo vinfo;
53
struct native_config config;
54
struct native_connector connector;
55
struct native_mode mode;
57
struct fbdev_surface *current_surface;
60
struct fbdev_surface {
61
struct native_surface base;
63
struct fbdev_display *fbdpy;
64
struct resource_surface *rsurf;
67
unsigned int sequence_number;
72
static INLINE struct fbdev_display *
73
fbdev_display(const struct native_display *ndpy)
75
return (struct fbdev_display *) ndpy;
78
static INLINE struct fbdev_surface *
79
fbdev_surface(const struct native_surface *nsurf)
81
return (struct fbdev_surface *) nsurf;
85
fbdev_surface_validate(struct native_surface *nsurf, uint attachment_mask,
86
unsigned int *seq_num, struct pipe_resource **textures,
87
int *width, int *height)
89
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
91
if (!resource_surface_add_resources(fbsurf->rsurf, attachment_mask))
94
resource_surface_get_resources(fbsurf->rsurf, textures, attachment_mask);
97
*seq_num = fbsurf->sequence_number;
99
*width = fbsurf->width;
101
*height = fbsurf->height;
107
fbdev_surface_flush_frontbuffer(struct native_surface *nsurf)
109
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
111
if (!fbsurf->is_current)
114
return resource_surface_present(fbsurf->rsurf,
115
NATIVE_ATTACHMENT_FRONT_LEFT, NULL);
119
fbdev_surface_swap_buffers(struct native_surface *nsurf)
121
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
122
struct fbdev_display *fbdpy = fbsurf->fbdpy;
125
if (fbsurf->is_current) {
126
ret = resource_surface_present(fbsurf->rsurf,
127
NATIVE_ATTACHMENT_BACK_LEFT, NULL);
130
resource_surface_swap_buffers(fbsurf->rsurf,
131
NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE);
132
/* the front/back textures are swapped */
133
fbsurf->sequence_number++;
134
fbdpy->event_handler->invalid_surface(&fbdpy->base,
135
&fbsurf->base, fbsurf->sequence_number);
141
fbdev_surface_wait(struct native_surface *nsurf)
147
fbdev_surface_destroy(struct native_surface *nsurf)
149
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
151
resource_surface_destroy(fbsurf->rsurf);
155
static struct native_surface *
156
fbdev_display_create_scanout_surface(struct native_display *ndpy,
157
const struct native_config *nconf,
158
uint width, uint height)
160
struct fbdev_display *fbdpy = fbdev_display(ndpy);
161
struct fbdev_surface *fbsurf;
163
fbsurf = CALLOC_STRUCT(fbdev_surface);
167
fbsurf->fbdpy = fbdpy;
168
fbsurf->width = width;
169
fbsurf->height = height;
171
fbsurf->rsurf = resource_surface_create(fbdpy->base.screen,
173
PIPE_BIND_RENDER_TARGET |
174
PIPE_BIND_DISPLAY_TARGET |
176
if (!fbsurf->rsurf) {
181
resource_surface_set_size(fbsurf->rsurf, fbsurf->width, fbsurf->height);
183
fbsurf->base.destroy = fbdev_surface_destroy;
184
fbsurf->base.swap_buffers = fbdev_surface_swap_buffers;
185
fbsurf->base.flush_frontbuffer = fbdev_surface_flush_frontbuffer;
186
fbsurf->base.validate = fbdev_surface_validate;
187
fbsurf->base.wait = fbdev_surface_wait;
189
return &fbsurf->base;
193
fbdev_display_program(struct native_display *ndpy, int crtc_idx,
194
struct native_surface *nsurf, uint x, uint y,
195
const struct native_connector **nconns, int num_nconns,
196
const struct native_mode *nmode)
198
struct fbdev_display *fbdpy = fbdev_display(ndpy);
199
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
204
if (fbdpy->current_surface) {
205
if (fbdpy->current_surface == fbsurf)
207
fbdpy->current_surface->is_current = FALSE;
211
fbsurf->is_current = TRUE;
212
fbdpy->current_surface = fbsurf;
217
static const struct native_mode **
218
fbdev_display_get_modes(struct native_display *ndpy,
219
const struct native_connector *nconn,
222
struct fbdev_display *fbdpy = fbdev_display(ndpy);
223
const struct native_mode **modes;
225
modes = MALLOC(sizeof(*modes));
227
modes[0] = &fbdpy->mode;
235
static const struct native_connector **
236
fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors,
239
struct fbdev_display *fbdpy = fbdev_display(ndpy);
240
const struct native_connector **connectors;
242
connectors = MALLOC(sizeof(*connectors));
244
connectors[0] = &fbdpy->connector;
252
static struct native_display_modeset fbdev_display_modeset = {
253
.get_connectors = fbdev_display_get_connectors,
254
.get_modes = fbdev_display_get_modes,
255
.create_scanout_surface = fbdev_display_create_scanout_surface,
256
.program = fbdev_display_program
259
static const struct native_config **
260
fbdev_display_get_configs(struct native_display *ndpy, int *num_configs)
262
struct fbdev_display *fbdpy = fbdev_display(ndpy);
263
const struct native_config **configs;
265
configs = MALLOC(sizeof(*configs));
267
configs[0] = &fbdpy->config;
276
fbdev_display_get_param(struct native_display *ndpy,
277
enum native_param_type param)
291
fbdev_display_destroy(struct native_display *ndpy)
293
struct fbdev_display *fbdpy = fbdev_display(ndpy);
295
fbdpy->base.screen->destroy(fbdpy->base.screen);
301
fbdev_display_init_modes(struct native_display *ndpy)
303
struct fbdev_display *fbdpy = fbdev_display(ndpy);
304
struct native_mode *nmode = &fbdpy->mode;
306
nmode->desc = "Current Mode";
307
nmode->width = fbdpy->vinfo.xres;
308
nmode->height = fbdpy->vinfo.yres;
309
nmode->refresh_rate = 60 * 1000; /* dummy */
315
fbdev_display_init_connectors(struct native_display *ndpy)
320
static enum pipe_format
321
vinfo_to_format(const struct fb_var_screeninfo *vinfo)
323
enum pipe_format format = PIPE_FORMAT_NONE;
325
switch (vinfo->bits_per_pixel) {
327
if (vinfo->red.length == 8 &&
328
vinfo->green.length == 8 &&
329
vinfo->blue.length == 8) {
330
format = (vinfo->transp.length == 8) ?
331
PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM;
335
if (vinfo->red.length == 5 &&
336
vinfo->green.length == 6 &&
337
vinfo->blue.length == 5 &&
338
vinfo->transp.length == 0)
339
format = PIPE_FORMAT_B5G6R5_UNORM;
349
fbdev_display_init_configs(struct native_display *ndpy)
351
struct fbdev_display *fbdpy = fbdev_display(ndpy);
352
struct native_config *nconf = &fbdpy->config;
354
nconf->color_format = vinfo_to_format(&fbdpy->vinfo);
355
if (nconf->color_format == PIPE_FORMAT_NONE)
359
(1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
360
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
362
nconf->scanout_bit = TRUE;
368
fbdev_display_init(struct native_display *ndpy)
370
struct fbdev_display *fbdpy = fbdev_display(ndpy);
371
struct sw_winsys *ws;
373
if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo))
376
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->vinfo))
379
if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR ||
380
fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS)
383
if (!fbdev_display_init_configs(&fbdpy->base) ||
384
!fbdev_display_init_connectors(&fbdpy->base) ||
385
!fbdev_display_init_modes(&fbdpy->base))
388
ws = fbdev_create_sw_winsys(fbdpy->fd, fbdpy->config.color_format);
391
fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws);
394
if (fbdpy->base.screen) {
395
if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen,
396
fbdpy->config.color_format, PIPE_TEXTURE_2D, 0,
397
PIPE_BIND_RENDER_TARGET, 0)) {
398
fbdpy->base.screen->destroy(fbdpy->base.screen);
399
fbdpy->base.screen = NULL;
403
return (fbdpy->base.screen != NULL);
406
static struct native_display *
407
fbdev_display_create(int fd, struct native_event_handler *event_handler,
410
struct fbdev_display *fbdpy;
412
fbdpy = CALLOC_STRUCT(fbdev_display);
417
fbdpy->event_handler = event_handler;
418
fbdpy->base.user_data = user_data;
420
if (!fbdev_display_init(&fbdpy->base)) {
425
fbdpy->base.destroy = fbdev_display_destroy;
426
fbdpy->base.get_param = fbdev_display_get_param;
427
fbdpy->base.get_configs = fbdev_display_get_configs;
429
fbdpy->base.modeset = &fbdev_display_modeset;
434
static struct native_display *
435
native_create_display(void *dpy, struct native_event_handler *event_handler,
438
struct native_display *ndpy;
441
/* well, this makes fd 0 being ignored */
443
fd = open("/dev/fb0", O_RDWR);
446
fd = dup((int) pointer_to_intptr(dpy));
451
ndpy = fbdev_display_create(fd, event_handler, user_data);
458
static const struct native_platform fbdev_platform = {
460
native_create_display
463
const struct native_platform *
464
native_get_fbdev_platform(void)
466
return &fbdev_platform;