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