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
);
390 fbdpy
->base
.screen
= native_create_sw_screen(ws
);
392 if (fbdpy
->base
.screen
) {
393 if (!fbdpy
->base
.screen
->is_format_supported(fbdpy
->base
.screen
,
394 fbdpy
->config
.color_format
, PIPE_TEXTURE_2D
, 0,
395 PIPE_BIND_RENDER_TARGET
, 0)) {
396 fbdpy
->base
.screen
->destroy(fbdpy
->base
.screen
);
397 fbdpy
->base
.screen
= NULL
;
401 return (fbdpy
->base
.screen
!= NULL
);
404 static struct native_display
*
405 fbdev_display_create(int fd
, struct native_event_handler
*event_handler
)
407 struct fbdev_display
*fbdpy
;
409 fbdpy
= CALLOC_STRUCT(fbdev_display
);
414 fbdpy
->event_handler
= event_handler
;
416 if (!fbdev_display_init(&fbdpy
->base
)) {
421 fbdpy
->base
.destroy
= fbdev_display_destroy
;
422 fbdpy
->base
.get_param
= fbdev_display_get_param
;
423 fbdpy
->base
.get_configs
= fbdev_display_get_configs
;
425 fbdpy
->base
.modeset
= &fbdev_display_modeset
;
430 struct native_probe
*
431 native_create_probe(EGLNativeDisplayType dpy
)
436 enum native_probe_result
437 native_get_probe_result(struct native_probe
*nprobe
)
439 return NATIVE_PROBE_UNKNOWN
;
443 native_get_name(void)
448 struct native_display
*
449 native_create_display(EGLNativeDisplayType dpy
,
450 struct native_event_handler
*event_handler
)
452 struct native_display
*ndpy
;
455 /* well, this makes fd 0 being ignored */
456 if (dpy
== EGL_DEFAULT_DISPLAY
) {
457 fd
= open("/dev/fb0", O_RDWR
);
460 fd
= dup((int) pointer_to_intptr((void *) dpy
));
465 ndpy
= fbdev_display_create(fd
, event_handler
);