1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4 *               Alexander Warg <warg@os.inf.tu-dresden.de>
5 *     economic rights: Technische Universität Dresden (Germany)
6 *
7 * This file is part of TUD:OS and distributed under the terms of the
8 * GNU General Public License 2.
9 * Please see the COPYING-GPL-2 file for details.
10 *
11 * As a special exception, you may use this file as part of a free software
12 * library without restriction.  Specifically, if other files instantiate
13 * templates or use macros or inline functions from this file, or you compile
14 * this file and link it with other files to produce an executable, this
15 * file does not by itself cause the resulting executable to be covered by
16 * the GNU General Public License.  This exception does not however
17 * invalidate any other reasons why the executable file might be covered by
18 * the GNU General Public License.
19 */
20#pragma once
21
22#include <l4/sys/capability>
23#include <l4/re/dataspace>
24#include <l4/re/video/colors>
25#include <l4/sys/cxx/ipc_iface>
26
27namespace L4Re { namespace Video {
28
29class L4_EXPORT Goos;
30
31/**
32 * View of a framebuffer.
33 *
34 * A view is a rectangular subset of a framebuffer managed by a Goos object.
35 * The Goos orders multiple views in a stack which determines which view is on
36 * top in case they overlap. The view's pixel data is provided by a backing
37 * buffer, which must belong to the Goos. It can be static or dynamically
38 * allocated, depending on the framebuffer.
39 *
40 * \see L4Re::Video::Goos
41 */
42class L4_EXPORT View
43{
44private:
45  friend class Goos;
46
47  L4::Cap<Goos> _goos;
48  unsigned _view_idx;
49
50  View(l4_cap_idx_t goos, unsigned idx)
51  : _goos(goos), _view_idx(_goos.is_valid() ? idx : ~0U) {}
52
53  unsigned view_index() const noexcept
54  { return _goos.is_valid() ? _view_idx : ~0U; }
55
56public:
57  View() : _goos(L4::Cap<Goos>::Invalid), _view_idx(~0U) {}
58
59  /**
60   * \brief Flags on a view.
61   */
62  enum Flags
63  {
64    F_none               = 0x00, ///< everything for this view is static (the VESA-FB case)
65    F_set_buffer         = 0x01, ///< buffer object for this view can be changed
66    F_set_buffer_offset  = 0x02, ///< buffer offset can be set
67    F_set_bytes_per_line = 0x04, ///< bytes per line can be set
68    F_set_pixel          = 0x08, ///< pixel type can be set
69    F_set_position       = 0x10, ///< position on screen can be set
70    F_dyn_allocated      = 0x20, ///< View is dynamically allocated
71    F_set_background     = 0x40, ///< Set view as background for session
72    F_set_flags          = 0x80, ///< Set view flags (\see V_flags)
73
74    /** Flags for a fully dynamic view */
75    F_fully_dynamic      =   F_set_buffer | F_set_buffer_offset | F_set_bytes_per_line
76                           | F_set_pixel | F_set_position | F_dyn_allocated,
77  };
78
79  /**
80   * \brief Property flags of a view.
81   *
82   * Such flags can be set or deleted with the #F_set_flags operation using
83   * the `set_info()` method.
84   */
85  enum V_flags
86  {
87    F_above              = 0x1000,  ///< Flag the view as stay on top
88    F_flags_mask         = 0xff000, ///< Mask containing all possible property flags
89  };
90
91  /**
92   * \brief Information structure of a view.
93   */
94  struct Info
95  {
96    unsigned flags;                 ///< Flags, see #Flags and #V_flags
97    unsigned view_index;            ///< Index of the view
98
99    unsigned long xpos;             ///< X position in pixels of the view in the Goos
100    unsigned long ypos;             ///< Y position in pixels of the view in the Goos
101    unsigned long width;            ///< Width of the view in pixels
102    unsigned long height;           ///< Height of the view in pixels
103    unsigned long buffer_offset;    ///< Offset in the memory buffer in bytes
104    unsigned long bytes_per_line;   ///< Bytes per line
105    Pixel_info pixel_info;          ///< Pixel information
106    unsigned buffer_index;          ///< Number of the buffer used for this view
107
108    /** Return whether the view has a static buffer */
109    bool has_static_buffer() const { return !(flags & F_set_buffer); }
110    /** Return whether the static buffer offset is available */
111    bool has_static_buffer_offset() const { return !(flags & F_set_buffer_offset); }
112
113    /** Return whether a buffer is set */
114    bool has_set_buffer() const { return flags & F_set_buffer; }
115    /** Return whether the given buffer offset is valid */
116    bool has_set_buffer_offset() const { return flags & F_set_buffer_offset; }
117    /** Return whether the given bytes-per-line value is valid */
118    bool has_set_bytes_per_line() const { return flags & F_set_bytes_per_line; }
119    /** Return whether the given pixel information is valid */
120    bool has_set_pixel() const { return flags & F_set_pixel; }
121    /** Return whether the position information given is valid */
122    bool has_set_position() const { return flags & F_set_position; }
123
124    /** Dump information on the view information to a stream */
125    template< typename OUT >
126    void dump(OUT &s) const
127    {
128      s.printf("View::Info:\n"
129               "  flags: %x\n"
130               "  size:  %ldx%ld\n"
131               "  pos:   %ldx%ld\n"
132               "  bytes_per_line: %ld\n"
133               "  buffer_offset:  %lx\n"
134               "  ",
135               flags, width, height, xpos, ypos,
136               bytes_per_line, buffer_offset);
137      pixel_info.dump(s);
138      s.printf("\n");
139    }
140  };
141
142  /**
143   * \brief Return the view information of the view.
144   * \param[out] info   Information structure pointer.
145   *
146   * \retval 0   Success
147   * \retval <0  Error
148   */
149  int info(Info *info) const noexcept;
150
151  /**
152   * \brief Set the information structure for this view.
153   * \param info  Information structure.
154   *
155   * \retval 0   Success
156   * \retval <0  Error
157   *
158   * The function will also set the view port according to the values given
159   * in the information structure.
160   */
161  int set_info(Info const &info) const noexcept;
162
163  /**
164   * \brief Set the position of the view in the Goos.
165   * \param scr_x      X position
166   * \param scr_y      Y position
167   * \param w          Width
168   * \param h          Height
169   * \param buf_offset Offset in the buffer in bytes
170   *
171   * \retval 0   Success
172   * \retval <0  Error
173   */
174  int set_viewport(int scr_x, int scr_y, int w, int h, unsigned long buf_offset) const noexcept;
175
176  /**
177   * \brief Move this view in the view stack.
178   * \param pivot   View to move relative to
179   * \param behind  When true move the view behind the pivot view, if false
180   *                move the view before the pivot view.
181   *
182   * \retval 0   Success
183   * \retval <0  Error
184   */
185  int stack(View const &pivot, bool behind = true) const noexcept;
186
187  /** Make this view the top-most view */
188  int push_top() const noexcept
189  { return stack(View(), true); }
190
191  /** Push this view the back */
192  int push_bottom() const noexcept
193  { return stack(View(), false); }
194
195  /**
196   * \brief Refresh/Redraw the view.
197   * \param x  X position.
198   * \param y  Y position.
199   * \param w  Width.
200   * \param h  Height.
201   *
202   * \retval 0   Success
203   * \retval <0  Error
204   */
205  int refresh(int x, int y, int w, int h) const noexcept;
206
207  /** \brief Return whether this view is valid */
208  bool valid() const { return _goos.is_valid(); }
209};
210
211
212/**
213 * Class that abstracts framebuffers.
214 *
215 * A framebuffer is the pixel data that is displayed on a screen and a Goos
216 * object lets the user manipulate that data. A Goos makes use of two kinds of
217 * objects:
218 * - Buffers in the form of L4Re::Dataspace objects. These hold the bytes for
219 *   the pixel data.
220 * - L4Re::Video::View objects.
221 *
222 * Both can either be static, that is their number and configuration is fixed
223 * and determined by the framebuffer, or they can be dynamic, with the user
224 * allocating them.
225 */
226class L4_EXPORT Goos :
227  public L4::Kobject_t<Goos, L4::Kobject, L4RE_PROTO_GOOS>
228{
229public:
230  /** Flags for a Goos */
231  enum Flags
232  {
233    F_auto_refresh    = 0x01, ///< The graphics display is automatically refreshed
234    F_pointer         = 0x02, ///< We have a mouse pointer
235    F_dynamic_views   = 0x04, ///< Supports dynamically allocated views
236    F_dynamic_buffers = 0x08, ///< Supports dynamically allocated buffers
237  };
238
239  /** Information structure of a Goos */
240  struct Info
241  {
242    unsigned long width;          ///< Width
243    unsigned long height;         ///< Height
244    unsigned flags;               ///< Flags, see #Flags
245    unsigned num_static_views;    ///< Number of static view
246    unsigned num_static_buffers;  ///< Number of static buffers
247    Pixel_info pixel_info;        ///< Pixel information
248
249    /** Return whether this Goos does auto refreshing or the view refresh
250     * functions must be used to make changes visible. */
251    bool auto_refresh() const { return flags & F_auto_refresh; }
252    /** Return whether a pointer is used by the provider of the Goos */
253    bool has_pointer() const { return flags & F_pointer; }
254    /** Return whether dynamic view are supported */
255    bool has_dynamic_views() const { return flags & F_dynamic_views; }
256    /** Return whether dynamic buffers are supported */
257    bool has_dynamic_buffers() const { return flags & F_dynamic_buffers; }
258
259    Info()
260    : width(0), height(0), flags(0), num_static_views(0),
261      num_static_buffers(0) {}
262  };
263
264  /**
265   * \brief Return the Goos information of the Goos.
266   * \param[out] info   Goos information structure pointer.
267   *
268   * \retval 0   Success
269   * \retval <0  Error
270   */
271  L4_INLINE_RPC(long, info, (Info *info));
272
273  /**
274   * \brief Return a static buffer of a Goos.
275   * \param idx     Index of the static buffer.
276   * \param rbuf    Capability slot to point the buffer dataspace to.
277   *
278   * \retval 0   Success
279   * \retval <0  Error
280   */
281  L4_RPC(long, get_static_buffer, (unsigned idx,
282                                   L4::Ipc::Out<L4::Cap<L4Re::Dataspace> > rbuf));
283
284  /**
285   * \brief Create a buffer.
286   * \param size     Size of buffer in bytes.
287   * \param rbuf     Capability slot to point the buffer dataspace to.
288   *
289   * \retval >=0  Success, the value returned is the buffer index.
290   * \retval <0   Error
291   */
292  L4_RPC(long, create_buffer, (unsigned long size,
293                               L4::Ipc::Out<L4::Cap<L4Re::Dataspace> > rbuf));
294
295  /**
296   * \brief Delete a buffer.
297   * \param idx      Buffer to delete.
298   *
299   * \retval 0   Success
300   * \retval <0  Error
301   */
302  L4_INLINE_RPC(long, delete_buffer, (unsigned idx));
303
304  // Use a wrapper for this RPC as we enacapsulate the View
305  L4_INLINE_RPC_NF(long, create_view, ());
306
307  /**
308   * \brief Create a view.
309   * \param[out] view   A view object.
310   * \param  utcb  UTCB of the caller. This is a default parameter.
311   *
312   * \retval >=0  Success, the value returned is the view index.
313   * \retval <0  Error
314   */
315  int create_view(View *view, l4_utcb_t *utcb = l4_utcb()) const noexcept
316  {
317    long r = create_view_t::call(c(), utcb);
318    if (r < 0)
319      return r;
320    *view = View(cap(), r);
321    return r;
322  }
323
324  // Use a wrapper as Views are encapsulated
325  L4_INLINE_RPC_NF(long, delete_view, (unsigned index));
326
327  /**
328   * \brief Delete a view.
329   * \param  v     The view object to delete.
330   * \param  utcb  UTCB of the caller. This is a default parameter.
331   *
332   * \retval 0   Success
333   * \retval <0  Error
334   */
335  int delete_view(View const &v, l4_utcb_t *utcb = l4_utcb()) const noexcept
336  {
337    return delete_view_t::call(c(), v._view_idx, utcb);
338  }
339
340  /**
341   * \brief Return a view.
342   * \param index   Index of the view to return.
343   * \return The view.
344   */
345  View view(unsigned index) const noexcept;
346
347  /**
348   * \brief Trigger refreshing of the given area on the virtual screen.
349   */
350  L4_INLINE_RPC(long, refresh, (int x, int y, int w, int h));
351
352  // those are used by the View
353  L4_INLINE_RPC(long, view_info, (unsigned index, View::Info *info));
354  L4_INLINE_RPC(long, set_view_info, (unsigned index, View::Info const &info));
355  L4_INLINE_RPC(long, view_stack, (unsigned index, unsigned pivit, bool behind));
356  L4_INLINE_RPC(long, view_refresh, (unsigned index, int x, int y, int w, int h));
357
358  typedef L4::Typeid::Rpcs<
359    info_t, get_static_buffer_t, create_buffer_t, create_view_t, delete_buffer_t,
360    delete_view_t, view_info_t, set_view_info_t, view_stack_t, view_refresh_t,
361    refresh_t
362  > Rpcs;
363};
364
365inline View
366Goos::view(unsigned index) const noexcept
367{ return View(cap(), index); }
368
369inline int
370View::info(Info *info) const noexcept
371{ return _goos->view_info(_view_idx, info); }
372
373inline int
374View::set_info(Info const &info) const noexcept
375{ return _goos->set_view_info(_view_idx, info); }
376
377inline int
378View::stack(View const &pivot, bool behind) const noexcept
379{ return _goos->view_stack(_view_idx, pivot._view_idx, behind); }
380
381inline int
382View::refresh(int x, int y, int w, int h) const noexcept
383{ return _goos->view_refresh(_view_idx, x, y, w, h); }
384
385inline int
386View::set_viewport(int scr_x, int scr_y, int w, int h,
387                   unsigned long buf_offset) const noexcept
388{
389  Info i;
390  i.flags = F_set_buffer_offset | F_set_position;
391  i.buffer_offset = buf_offset;
392  i.xpos = scr_x;
393  i.ypos = scr_y;
394  i.width = w;
395  i.height = h;
396  return set_info(i);
397}
398
399}}
400