The Pedigree Project  0.1
fb.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/fb.h>
25 #include <sys/ioctl.h>
26 #include <sys/klog.h>
27 #include <sys/mman.h>
28 #include <unistd.h>
29 
30 #include "pedigree/native/graphics/Graphics.h"
31 
32 #include "pedigree_fb.h"
33 
34 Framebuffer::Framebuffer()
35  : m_pFramebuffer(0), m_FramebufferSize(0), m_Format(), m_Width(0),
36  m_Height(0), m_Fb(-1), m_bStoredMode(false), m_StoredMode()
37 {
38 }
39 
40 Framebuffer::~Framebuffer()
41 {
42  if (m_pFramebuffer)
43  {
44  munmap(m_pFramebuffer, m_FramebufferSize);
45  m_pFramebuffer = 0;
46  m_FramebufferSize = 0;
47  }
48 
49  if (m_Fb >= 0)
50  {
51  close(m_Fb);
52  m_Fb = -1;
53  }
54 }
55 
57 {
58  // Grab a framebuffer to use.
59  m_Fb = open("/dev/fb", O_RDWR);
60  if (m_Fb < 0)
61  {
62  klog(LOG_INFO, "libfb: no framebuffer device");
63  fprintf(stderr, "libfb: couldn't open framebuffer device");
64  return false;
65  }
66 
67  return true;
68 }
69 
71 {
72  if (m_bStoredMode)
73  return;
74 
75  // Grab the current mode so we can restore it if we die.
76  pedigree_fb_mode current_mode;
77  int result = ioctl(m_Fb, PEDIGREE_FB_GETMODE, &current_mode);
78  if (result == 0)
79  {
80  m_bStoredMode = true;
81  m_StoredMode = current_mode;
82  }
83 }
84 
86 {
87  if (!m_bStoredMode)
88  return;
89 
90  // Restore old graphics mode.
91  pedigree_fb_modeset old_mode = {m_StoredMode.width, m_StoredMode.height,
92  m_StoredMode.depth};
93  ioctl(m_Fb, PEDIGREE_FB_SETMODE, &old_mode);
94 
95  m_bStoredMode = false;
96 }
97 
98 int Framebuffer::enterMode(size_t desiredW, size_t desiredH, size_t desiredBpp)
99 {
100  // All good, framebuffer already exists.
101  if (m_pFramebuffer)
102  return 0;
103 
104  // Can we set the graphics mode we want?
105  pedigree_fb_modeset mode = {desiredW, desiredH, desiredBpp};
106  int result = ioctl(m_Fb, PEDIGREE_FB_SETMODE, &mode);
107  if (result < 0)
108  {
109  // No! Bad!
113  klog(LOG_INFO, "libfb: can't set the desired mode");
114  fprintf(
115  stderr,
116  "libfb: could not set desired mode (%ux%u) in any colour depth.\n",
117  mode.width, mode.height);
118  return EXIT_FAILURE;
119  }
120 
121  pedigree_fb_mode set_mode;
122  result = ioctl(m_Fb, PEDIGREE_FB_GETMODE, &set_mode);
123  if (result < 0)
124  {
125  klog(LOG_INFO, "libfb: can't get mode info");
126  fprintf(
127  stderr,
128  "libfb: could not get mode information after setting mode.\n");
129 
130  // Back to text.
131  memset(&mode, 0, sizeof(mode));
132  ioctl(m_Fb, PEDIGREE_FB_SETMODE, &mode);
133  return EXIT_FAILURE;
134  }
135 
136  m_Width = set_mode.width;
137  m_Height = set_mode.height;
138 
139  m_Format = CAIRO_FORMAT_ARGB32;
140  if (set_mode.format == PedigreeGraphics::Bits24_Rgb)
141  {
142  if (set_mode.bytes_per_pixel != 4)
143  {
144  fprintf(
145  stderr, "libfb: error: incompatible framebuffer format (bytes "
146  "per pixel)\n");
147  return EXIT_FAILURE;
148  }
149  }
150  else if (set_mode.format == PedigreeGraphics::Bits16_Rgb565)
151  {
152  m_Format = CAIRO_FORMAT_RGB16_565;
153  }
154  else if (set_mode.format > PedigreeGraphics::Bits32_Rgb)
155  {
156  fprintf(
157  stderr, "libfb: error: incompatible framebuffer format (possibly "
158  "BGR or similar)\n");
159  return EXIT_FAILURE;
160  }
161 
162  int stride = cairo_format_stride_for_width(m_Format, set_mode.width);
163 
164  // Map the framebuffer in to our address space.
165  klog(LOG_INFO, "Mapping /dev/fb in (sz=%x)...", stride * set_mode.height);
166  m_pFramebuffer = mmap(
167  0, stride * set_mode.height, PROT_READ | PROT_WRITE, MAP_SHARED, m_Fb,
168  0);
169  klog(LOG_INFO, "Got %p...", m_pFramebuffer);
170 
171  if (m_pFramebuffer == MAP_FAILED)
172  {
173  klog(LOG_CRIT, "libfb: couldn't map framebuffer into address space");
174  return EXIT_FAILURE;
175  }
176  else
177  {
178  klog(LOG_INFO, "libfb: mapped framebuffer at %p", m_pFramebuffer);
179  }
180 
181  m_FramebufferSize = stride * set_mode.height;
182 
183  return 0;
184 }
185 
186 void Framebuffer::flush(size_t x, size_t y, size_t w, size_t h)
187 {
188  // Submit a redraw to the graphics card.
189  pedigree_fb_rect fbdirty = {x, y, w, h};
190  ioctl(m_Fb, PEDIGREE_FB_REDRAW, &fbdirty);
191 }
void restoreMode()
Definition: fb.cc:85
int enterMode(size_t desiredW, size_t desiredH, size_t desiredBpp)
Definition: fb.cc:98
bool initialise()
Definition: fb.cc:56
All zeroes = &#39;revert to text mode&#39;.
Definition: fb.h:37
void flush(size_t x, size_t y, size_t w, size_t h)
Definition: fb.cc:186
void storeMode()
Definition: fb.cc:70
virtual File * open()
Definition: File.cc:572