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_present(struct native_surface
*nsurf
,
142 enum native_attachment natt
,
148 if (preserve
|| swap_interval
)
152 case NATIVE_ATTACHMENT_FRONT_LEFT
:
153 ret
= fbdev_surface_flush_frontbuffer(nsurf
);
155 case NATIVE_ATTACHMENT_BACK_LEFT
:
156 ret
= fbdev_surface_swap_buffers(nsurf
);
167 fbdev_surface_wait(struct native_surface
*nsurf
)
173 fbdev_surface_destroy(struct native_surface
*nsurf
)
175 struct fbdev_surface
*fbsurf
= fbdev_surface(nsurf
);
177 resource_surface_destroy(fbsurf
->rsurf
);
181 static struct native_surface
*
182 fbdev_display_create_scanout_surface(struct native_display
*ndpy
,
183 const struct native_config
*nconf
,
184 uint width
, uint height
)
186 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
187 struct fbdev_surface
*fbsurf
;
189 fbsurf
= CALLOC_STRUCT(fbdev_surface
);
193 fbsurf
->fbdpy
= fbdpy
;
194 fbsurf
->width
= width
;
195 fbsurf
->height
= height
;
197 fbsurf
->rsurf
= resource_surface_create(fbdpy
->base
.screen
,
199 PIPE_BIND_RENDER_TARGET
|
200 PIPE_BIND_DISPLAY_TARGET
|
202 if (!fbsurf
->rsurf
) {
207 resource_surface_set_size(fbsurf
->rsurf
, fbsurf
->width
, fbsurf
->height
);
209 fbsurf
->base
.destroy
= fbdev_surface_destroy
;
210 fbsurf
->base
.swap_buffers
= fbdev_surface_swap_buffers
;
211 fbsurf
->base
.flush_frontbuffer
= fbdev_surface_flush_frontbuffer
;
212 fbsurf
->base
.present
= fbdev_surface_present
;
213 fbsurf
->base
.validate
= fbdev_surface_validate
;
214 fbsurf
->base
.wait
= fbdev_surface_wait
;
216 return &fbsurf
->base
;
220 fbdev_display_program(struct native_display
*ndpy
, int crtc_idx
,
221 struct native_surface
*nsurf
, uint x
, uint y
,
222 const struct native_connector
**nconns
, int num_nconns
,
223 const struct native_mode
*nmode
)
225 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
226 struct fbdev_surface
*fbsurf
= fbdev_surface(nsurf
);
231 if (fbdpy
->current_surface
) {
232 if (fbdpy
->current_surface
== fbsurf
)
234 fbdpy
->current_surface
->is_current
= FALSE
;
238 fbsurf
->is_current
= TRUE
;
239 fbdpy
->current_surface
= fbsurf
;
244 static const struct native_mode
**
245 fbdev_display_get_modes(struct native_display
*ndpy
,
246 const struct native_connector
*nconn
,
249 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
250 const struct native_mode
**modes
;
252 modes
= MALLOC(sizeof(*modes
));
254 modes
[0] = &fbdpy
->mode
;
262 static const struct native_connector
**
263 fbdev_display_get_connectors(struct native_display
*ndpy
, int *num_connectors
,
266 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
267 const struct native_connector
**connectors
;
269 connectors
= MALLOC(sizeof(*connectors
));
271 connectors
[0] = &fbdpy
->connector
;
279 static struct native_display_modeset fbdev_display_modeset
= {
280 .get_connectors
= fbdev_display_get_connectors
,
281 .get_modes
= fbdev_display_get_modes
,
282 .create_scanout_surface
= fbdev_display_create_scanout_surface
,
283 .program
= fbdev_display_program
286 static const struct native_config
**
287 fbdev_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
289 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
290 const struct native_config
**configs
;
292 configs
= MALLOC(sizeof(*configs
));
294 configs
[0] = &fbdpy
->config
;
303 fbdev_display_get_param(struct native_display
*ndpy
,
304 enum native_param_type param
)
309 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
310 case NATIVE_PARAM_PRESERVE_BUFFER
:
311 case NATIVE_PARAM_MAX_SWAP_INTERVAL
:
321 fbdev_display_destroy(struct native_display
*ndpy
)
323 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
325 fbdpy
->base
.screen
->destroy(fbdpy
->base
.screen
);
331 fbdev_display_init_modes(struct native_display
*ndpy
)
333 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
334 struct native_mode
*nmode
= &fbdpy
->mode
;
336 nmode
->desc
= "Current Mode";
337 nmode
->width
= fbdpy
->vinfo
.xres
;
338 nmode
->height
= fbdpy
->vinfo
.yres
;
339 nmode
->refresh_rate
= 60 * 1000; /* dummy */
345 fbdev_display_init_connectors(struct native_display
*ndpy
)
350 static enum pipe_format
351 vinfo_to_format(const struct fb_var_screeninfo
*vinfo
)
353 enum pipe_format format
= PIPE_FORMAT_NONE
;
355 switch (vinfo
->bits_per_pixel
) {
357 if (vinfo
->red
.length
== 8 &&
358 vinfo
->green
.length
== 8 &&
359 vinfo
->blue
.length
== 8) {
360 format
= (vinfo
->transp
.length
== 8) ?
361 PIPE_FORMAT_B8G8R8A8_UNORM
: PIPE_FORMAT_B8G8R8X8_UNORM
;
365 if (vinfo
->red
.length
== 5 &&
366 vinfo
->green
.length
== 6 &&
367 vinfo
->blue
.length
== 5 &&
368 vinfo
->transp
.length
== 0)
369 format
= PIPE_FORMAT_B5G6R5_UNORM
;
379 fbdev_display_init_configs(struct native_display
*ndpy
)
381 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
382 struct native_config
*nconf
= &fbdpy
->config
;
384 nconf
->color_format
= vinfo_to_format(&fbdpy
->vinfo
);
385 if (nconf
->color_format
== PIPE_FORMAT_NONE
)
389 (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
390 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
392 nconf
->scanout_bit
= TRUE
;
398 fbdev_display_init(struct native_display
*ndpy
)
400 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
401 struct sw_winsys
*ws
;
403 if (ioctl(fbdpy
->fd
, FBIOGET_FSCREENINFO
, &fbdpy
->finfo
))
406 if (ioctl(fbdpy
->fd
, FBIOGET_VSCREENINFO
, &fbdpy
->vinfo
))
409 if (fbdpy
->finfo
.visual
!= FB_VISUAL_TRUECOLOR
||
410 fbdpy
->finfo
.type
!= FB_TYPE_PACKED_PIXELS
)
413 if (!fbdev_display_init_configs(&fbdpy
->base
) ||
414 !fbdev_display_init_connectors(&fbdpy
->base
) ||
415 !fbdev_display_init_modes(&fbdpy
->base
))
418 ws
= fbdev_create_sw_winsys(fbdpy
->fd
, fbdpy
->config
.color_format
);
421 fbdpy
->event_handler
->new_sw_screen(&fbdpy
->base
, ws
);
424 if (fbdpy
->base
.screen
) {
425 if (!fbdpy
->base
.screen
->is_format_supported(fbdpy
->base
.screen
,
426 fbdpy
->config
.color_format
, PIPE_TEXTURE_2D
, 0,
427 PIPE_BIND_RENDER_TARGET
, 0)) {
428 fbdpy
->base
.screen
->destroy(fbdpy
->base
.screen
);
429 fbdpy
->base
.screen
= NULL
;
433 return (fbdpy
->base
.screen
!= NULL
);
436 static struct native_display
*
437 fbdev_display_create(int fd
, struct native_event_handler
*event_handler
,
440 struct fbdev_display
*fbdpy
;
442 fbdpy
= CALLOC_STRUCT(fbdev_display
);
447 fbdpy
->event_handler
= event_handler
;
448 fbdpy
->base
.user_data
= user_data
;
450 if (!fbdev_display_init(&fbdpy
->base
)) {
455 fbdpy
->base
.destroy
= fbdev_display_destroy
;
456 fbdpy
->base
.get_param
= fbdev_display_get_param
;
457 fbdpy
->base
.get_configs
= fbdev_display_get_configs
;
459 fbdpy
->base
.modeset
= &fbdev_display_modeset
;
464 static struct native_display
*
465 native_create_display(void *dpy
, struct native_event_handler
*event_handler
,
468 struct native_display
*ndpy
;
471 /* well, this makes fd 0 being ignored */
473 fd
= open("/dev/fb0", O_RDWR
);
476 fd
= dup((int) pointer_to_intptr(dpy
));
481 ndpy
= fbdev_display_create(fd
, event_handler
, user_data
);
488 static const struct native_platform fbdev_platform
= {
490 native_create_display
493 const struct native_platform
*
494 native_get_fbdev_platform(void)
496 return &fbdev_platform
;