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
.present
= fbdev_surface_present
;
211 fbsurf
->base
.validate
= fbdev_surface_validate
;
212 fbsurf
->base
.wait
= fbdev_surface_wait
;
214 return &fbsurf
->base
;
218 fbdev_display_program(struct native_display
*ndpy
, int crtc_idx
,
219 struct native_surface
*nsurf
, uint x
, uint y
,
220 const struct native_connector
**nconns
, int num_nconns
,
221 const struct native_mode
*nmode
)
223 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
224 struct fbdev_surface
*fbsurf
= fbdev_surface(nsurf
);
229 if (fbdpy
->current_surface
) {
230 if (fbdpy
->current_surface
== fbsurf
)
232 fbdpy
->current_surface
->is_current
= FALSE
;
236 fbsurf
->is_current
= TRUE
;
237 fbdpy
->current_surface
= fbsurf
;
242 static const struct native_mode
**
243 fbdev_display_get_modes(struct native_display
*ndpy
,
244 const struct native_connector
*nconn
,
247 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
248 const struct native_mode
**modes
;
250 modes
= MALLOC(sizeof(*modes
));
252 modes
[0] = &fbdpy
->mode
;
260 static const struct native_connector
**
261 fbdev_display_get_connectors(struct native_display
*ndpy
, int *num_connectors
,
264 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
265 const struct native_connector
**connectors
;
267 connectors
= MALLOC(sizeof(*connectors
));
269 connectors
[0] = &fbdpy
->connector
;
277 static struct native_display_modeset fbdev_display_modeset
= {
278 .get_connectors
= fbdev_display_get_connectors
,
279 .get_modes
= fbdev_display_get_modes
,
280 .create_scanout_surface
= fbdev_display_create_scanout_surface
,
281 .program
= fbdev_display_program
284 static const struct native_config
**
285 fbdev_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
287 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
288 const struct native_config
**configs
;
290 configs
= MALLOC(sizeof(*configs
));
292 configs
[0] = &fbdpy
->config
;
301 fbdev_display_get_param(struct native_display
*ndpy
,
302 enum native_param_type param
)
307 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
308 case NATIVE_PARAM_PRESERVE_BUFFER
:
309 case NATIVE_PARAM_MAX_SWAP_INTERVAL
:
319 fbdev_display_destroy(struct native_display
*ndpy
)
321 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
323 fbdpy
->base
.screen
->destroy(fbdpy
->base
.screen
);
329 fbdev_display_init_modes(struct native_display
*ndpy
)
331 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
332 struct native_mode
*nmode
= &fbdpy
->mode
;
334 nmode
->desc
= "Current Mode";
335 nmode
->width
= fbdpy
->vinfo
.xres
;
336 nmode
->height
= fbdpy
->vinfo
.yres
;
337 nmode
->refresh_rate
= 60 * 1000; /* dummy */
343 fbdev_display_init_connectors(struct native_display
*ndpy
)
348 static enum pipe_format
349 vinfo_to_format(const struct fb_var_screeninfo
*vinfo
)
351 enum pipe_format format
= PIPE_FORMAT_NONE
;
353 switch (vinfo
->bits_per_pixel
) {
355 if (vinfo
->red
.length
== 8 &&
356 vinfo
->green
.length
== 8 &&
357 vinfo
->blue
.length
== 8) {
358 format
= (vinfo
->transp
.length
== 8) ?
359 PIPE_FORMAT_B8G8R8A8_UNORM
: PIPE_FORMAT_B8G8R8X8_UNORM
;
363 if (vinfo
->red
.length
== 5 &&
364 vinfo
->green
.length
== 6 &&
365 vinfo
->blue
.length
== 5 &&
366 vinfo
->transp
.length
== 0)
367 format
= PIPE_FORMAT_B5G6R5_UNORM
;
377 fbdev_display_init_configs(struct native_display
*ndpy
)
379 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
380 struct native_config
*nconf
= &fbdpy
->config
;
382 nconf
->color_format
= vinfo_to_format(&fbdpy
->vinfo
);
383 if (nconf
->color_format
== PIPE_FORMAT_NONE
)
387 (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
388 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
390 nconf
->scanout_bit
= TRUE
;
396 fbdev_display_init(struct native_display
*ndpy
)
398 struct fbdev_display
*fbdpy
= fbdev_display(ndpy
);
399 struct sw_winsys
*ws
;
401 if (ioctl(fbdpy
->fd
, FBIOGET_FSCREENINFO
, &fbdpy
->finfo
))
404 if (ioctl(fbdpy
->fd
, FBIOGET_VSCREENINFO
, &fbdpy
->vinfo
))
407 if (fbdpy
->finfo
.visual
!= FB_VISUAL_TRUECOLOR
||
408 fbdpy
->finfo
.type
!= FB_TYPE_PACKED_PIXELS
)
411 if (!fbdev_display_init_configs(&fbdpy
->base
) ||
412 !fbdev_display_init_connectors(&fbdpy
->base
) ||
413 !fbdev_display_init_modes(&fbdpy
->base
))
416 ws
= fbdev_create_sw_winsys(fbdpy
->fd
, fbdpy
->config
.color_format
);
419 fbdpy
->event_handler
->new_sw_screen(&fbdpy
->base
, ws
);
422 if (fbdpy
->base
.screen
) {
423 if (!fbdpy
->base
.screen
->is_format_supported(fbdpy
->base
.screen
,
424 fbdpy
->config
.color_format
, PIPE_TEXTURE_2D
, 0,
425 PIPE_BIND_RENDER_TARGET
, 0)) {
426 fbdpy
->base
.screen
->destroy(fbdpy
->base
.screen
);
427 fbdpy
->base
.screen
= NULL
;
431 return (fbdpy
->base
.screen
!= NULL
);
434 static struct native_display
*
435 fbdev_display_create(int fd
, struct native_event_handler
*event_handler
,
438 struct fbdev_display
*fbdpy
;
440 fbdpy
= CALLOC_STRUCT(fbdev_display
);
445 fbdpy
->event_handler
= event_handler
;
446 fbdpy
->base
.user_data
= user_data
;
448 if (!fbdev_display_init(&fbdpy
->base
)) {
453 fbdpy
->base
.destroy
= fbdev_display_destroy
;
454 fbdpy
->base
.get_param
= fbdev_display_get_param
;
455 fbdpy
->base
.get_configs
= fbdev_display_get_configs
;
457 fbdpy
->base
.modeset
= &fbdev_display_modeset
;
462 static struct native_display
*
463 native_create_display(void *dpy
, struct native_event_handler
*event_handler
,
466 struct native_display
*ndpy
;
469 /* well, this makes fd 0 being ignored */
471 fd
= open("/dev/fb0", O_RDWR
);
474 fd
= dup((int) pointer_to_intptr(dpy
));
479 ndpy
= fbdev_display_create(fd
, event_handler
, user_data
);
486 static const struct native_platform fbdev_platform
= {
488 native_create_display
491 const struct native_platform
*
492 native_get_fbdev_platform(void)
494 return &fbdev_platform
;