v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Modules Pages
framebuffer.h
1 /* -*- mode: C; c-basic-offset: 4; intent-tabs-mode: nil -*-
2  *
3  * Sifteo SDK
4  *
5  * Copyright <c> 2012 Sifteo, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
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 THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #pragma once
27 #ifdef NOT_USERSPACE
28 # error This is a userspace-only header, not allowed by the current build.
29 #endif
30 
31 #include <sifteo/abi.h>
32 #include <sifteo/macros.h>
33 #include <sifteo/math.h>
34 
35 namespace Sifteo {
36 
50 template <unsigned tWidth, unsigned tHeight, unsigned tBitsPerPixel>
51 struct FBDrawable {
52  _SYSAttachedVideoBuffer sys;
53 
57  static unsigned width() {
58  return tWidth;
59  }
60 
64  static unsigned height() {
65  return tHeight;
66  }
67 
71  static UInt2 size() {
72  return vec(tWidth, tHeight);
73  }
74 
79  static unsigned numColors() {
80  return 1 << tBitsPerPixel;
81  }
82 
87  static unsigned bitsPerPixel() {
88  return tBitsPerPixel;
89  }
90 
94  static unsigned sizeInBytes() {
95  return tWidth * tHeight * tBitsPerPixel / 8;
96  }
97 
101  static unsigned sizeInWords() {
102  return tWidth * tHeight * tBitsPerPixel / 16;
103  }
104 
114  void plot(UInt2 pos, unsigned colorIndex)
115  {
116  ASSERT(pos.x <= tWidth && pos.y <= tHeight);
117 
118  const unsigned pixelsPerByte = 8 / tBitsPerPixel;
119  const unsigned bytesPerLine = tWidth / pixelsPerByte;
120  const unsigned xByte = pos.x / pixelsPerByte;
121  const unsigned xBit = (pos.x % pixelsPerByte) * tBitsPerPixel;
122  const unsigned byteAddr = xByte + pos.y * bytesPerLine;
123  const unsigned pixelMask = ((1 << tBitsPerPixel) - 1) << xBit;
124 
125  uint8_t byte = _SYS_vbuf_peekb(&sys.vbuf, byteAddr);
126  byte &= ~pixelMask;
127  byte |= colorIndex << xBit;
128  _SYS_vbuf_pokeb(&sys.vbuf, byteAddr, byte);
129  }
130 
138  static uint16_t expand16(unsigned colorIndex)
139  {
140  switch (tBitsPerPixel) {
141  case 1: return colorIndex ? 0xFFFF : 0x0000;
142  case 2: colorIndex |= colorIndex << 2;
143  case 4: colorIndex |= colorIndex << 4;
144  case 8: colorIndex |= colorIndex << 8;
145  case 16: return colorIndex;
146  default: ASSERT(0);
147  }
148  }
149 
156  void span(UInt2 pos, unsigned width, unsigned colorIndex)
157  {
158  ASSERT(pos.x <= tWidth && width <= tWidth &&
159  (pos.x + width) <= tWidth && pos.y < tHeight);
160 
161  const unsigned pixelsPerWord = 16 / tBitsPerPixel;
162  const unsigned wordsPerLine = tWidth / pixelsPerWord;
163  const unsigned colorWord = expand16(colorIndex);
164 
165  // Calculate a base address in words, and
166  // left/right boundaries relative to that in bits.
167  unsigned addr = pos.x / pixelsPerWord + pos.y * wordsPerLine;
168  int start = (pos.x % pixelsPerWord) * tBitsPerPixel;
169  int end = start + width * tBitsPerPixel;
170 
171  while (end > 0) {
172  if (start <= 0 && end >= 16) {
173  // A run of complete words
174 
175  unsigned count = end / 16;
176  _SYS_vbuf_fill(&sys.vbuf, addr, colorWord, count);
177  addr += count;
178  unsigned bits = count * 16;
179  start -= bits;
180  end -= bits;
181 
182  } else {
183  // One partial word. (The first, last or only word)
184 
185  unsigned mask = bitRange<uint16_t>(start, end);
186  unsigned word = _SYS_vbuf_peek(&sys.vbuf, addr);
187  word &= ~mask;
188  word |= colorWord & mask;
189  _SYS_vbuf_poke(&sys.vbuf, addr, word);
190  addr++;
191  start -= 16;
192  end -= 16;
193  }
194  }
195  }
196 
203  void fill(UInt2 topLeft, UInt2 size, unsigned colorIndex)
204  {
205  while (size.y) {
206  span(topLeft, size.x, colorIndex);
207  size.y--;
208  topLeft.y++;
209  }
210  }
211 
215  void fill(unsigned colorIndex)
216  {
217  _SYS_vbuf_fill(&sys.vbuf, 0, expand16(colorIndex), sizeInWords());
218  }
219 
226  void bitmapSpan(UInt2 pos, unsigned width, const uint8_t *data)
227  {
228  ASSERT(pos.x <= tWidth && width <= tWidth &&
229  (pos.x + width) <= tWidth && pos.y < tHeight);
230 
231  const unsigned pixelsPerByte = 8 / tBitsPerPixel;
232  const unsigned bytesPerLine = tWidth / pixelsPerByte;
233 
234  // Base address in bits
235  unsigned addr = pos.x / pixelsPerByte + pos.y * bytesPerLine;
236 
237  // Bitmap alignment
238  unsigned shift = (pos.x % pixelsPerByte) * tBitsPerPixel;
239  unsigned invShift = 8 - shift;
240 
241  // Initial mask range, in bits, relative to the base address
242  int start = shift;
243  int end = start + width * tBitsPerPixel;
244 
245  while (end > 0) {
246  // One source byte at a time, splatted to either one or two
247  // destination bytes in VRAM.
248 
249  uint8_t source = *data;
250  data++;
251 
252  // First byte
253  unsigned mask = (0xFF << shift) & bitRange<uint16_t>(start, end);
254  unsigned byte = _SYS_vbuf_peekb(&sys.vbuf, addr);
255  byte &= ~mask;
256  byte |= (source << shift) & mask;
257  _SYS_vbuf_pokeb(&sys.vbuf, addr, byte);
258 
259  addr++;
260  start -= 8;
261  end -= 8;
262 
263  // Optional second byte
264  if (shift) {
265  unsigned mask = (0xFF >> invShift) & bitRange<uint16_t>(start, end);
266  unsigned byte = _SYS_vbuf_peekb(&sys.vbuf, addr);
267  byte &= ~mask;
268  byte |= (source >> invShift) & mask;
269  _SYS_vbuf_pokeb(&sys.vbuf, addr, byte);
270  }
271  }
272  }
273 
286  void bitmap(UInt2 topLeft, UInt2 size, const uint8_t *data, unsigned stride)
287  {
288  while (size.y) {
289  bitmapSpan(topLeft, size.x, data);
290  size.y--;
291  topLeft.y++;
292  data += stride;
293  }
294  }
295 
301  void set(const uint16_t *data) {
302  _SYS_vbuf_write(&sys.vbuf, 0, data, sizeInWords());
303  }
304 
308  _SYSVideoBuffer &videoBuffer() {
309  return sys.vbuf;
310  }
311 
315  CubeID cube() const {
316  return sys.cube;
317  }
318 };
319 
320 
323 
326 
329 
330 
341  _SYSAttachedVideoBuffer sys;
342 
350  void resizeFB(Int2 pixelSize) {
351  ASSERT((pixelSize.x & 1) == 0 &&
352  pixelSize.x * pixelSize.y <= 1536 &&
353  pixelSize.x <= 128 &&
354  pixelSize.y <= 128);
355 
356  _SYS_vbuf_poke(&sys.vbuf, offsetof(_SYSVideoRAM, stamp_pitch)/2,
357  (pixelSize.x >> 1) | (pixelSize.y << 8));
358  }
359 
370  template <unsigned tWidth, unsigned tHeight>
372  {
373  auto &fb = *reinterpret_cast<FBDrawable<tWidth, tHeight, 4>*>(this);
374  ASSERT(&fb.sys == &sys);
375  return fb;
376  }
377 
387  template <unsigned tWidth, unsigned tHeight>
389  {
390  _SYS_finish();
391  resizeFB(vec(tWidth, tHeight));
392  return getFB<tWidth, tHeight>();
393  }
394 
403  void setHWindow(uint8_t firstColumn, uint8_t numColumns) {
404  _SYS_vbuf_poke(&sys.vbuf, offsetof(_SYSVideoRAM, stamp_x)/2,
405  firstColumn | (numColumns << 8));
406  }
407 
415  void setBox(Int2 topLeft, Int2 size) {
416  _SYS_vbuf_poke(&sys.vbuf, offsetof(_SYSVideoRAM, first_line)/2,
417  topLeft.y | (size.y << 8));
418  setHWindow(topLeft.x, size.x);
419  }
420 
427  void setKeyIndex(unsigned index) {
428  _SYS_vbuf_pokeb(&sys.vbuf, offsetof(_SYSVideoRAM, stamp_key), index);
429  }
430 
436  void disableKey() {
437  setKeyIndex(16);
438  }
439 
443  _SYSVideoBuffer &videoBuffer() {
444  return sys.vbuf;
445  }
446 
450  CubeID cube() const {
451  return sys.cube;
452  }
453 };
454 
455 
460 }; // namespace Sifteo
CubeID cube() const
Return the CubeID associated with this drawable.
Definition: framebuffer.h:450
FBDrawable< tWidth, tHeight, 4 > & getFB()
Obtain an FBDrawable accessor for the framebuffer memory, using the supplied framebuffer dimensions...
Definition: framebuffer.h:371
void span(UInt2 pos, unsigned width, unsigned colorIndex)
Plot a horizontal span of pixels, given the position of the leftmost pixel, and the number of pixels ...
Definition: framebuffer.h:156
#define offsetof(t, m)
Definition: macros.h:368
void setBox(Int2 topLeft, Int2 size)
Set both the horizontal and vertical windows, to define a 2D box of pixels that we'll draw into...
Definition: framebuffer.h:415
void plot(UInt2 pos, unsigned colorIndex)
Plot a single pixel, at the specified location.
Definition: framebuffer.h:114
_SYSVideoBuffer & videoBuffer()
Return the VideoBuffer associated with this drawable.
Definition: framebuffer.h:443
Generalized two-element cartesian coordinate vector.
Definition: math.h:488
#define ASSERT(_x)
Runtime debug assertion.
Definition: macros.h:205
void setHWindow(uint8_t firstColumn, uint8_t numColumns)
Set the horizontal window. This is the mode-specific X-axis counterpart to VideoBuffer::setWindow().
Definition: framebuffer.h:403
static UInt2 size()
Return the size of this mode as a vector, in pixels.
Definition: framebuffer.h:71
FBDrawable< 32, 32, 4 > FB32Drawable
Typedef for the FBDrawable instance used in FB32 mode.
Definition: framebuffer.h:322
FBDrawable< tWidth, tHeight, 4 > & initFB()
Obtain an FBDrawable accessor for the framebuffer memory, using the supplied framebuffer dimensions...
Definition: framebuffer.h:388
A VRAM accessor for the STAMP mode, a special purpose 16-color framebuffer mode which supports color-...
Definition: framebuffer.h:340
void set(const uint16_t *data)
Draw a pre-formatted bitmap to this framebuffer.
Definition: framebuffer.h:301
void bitmapSpan(UInt2 pos, unsigned width, const uint8_t *data)
Draw a span of pixels from a packed-pixel bitmap, of the same color depth as this framebuffer mode...
Definition: framebuffer.h:226
T x
Vector component X.
Definition: math.h:489
static unsigned numColors()
Return the total number of colors this mode supports. This is equal to the number of colormap entries...
Definition: framebuffer.h:79
A lightweight identifier for one Sifteo cube.
Definition: cube.h:85
CubeID cube() const
Return the CubeID associated with this drawable.
Definition: framebuffer.h:315
FBDrawable< 128, 48, 1 > FB128Drawable
Typedef for the FBDrawable instance used in FB128 mode.
Definition: framebuffer.h:328
static unsigned height()
Return the height, in pixels, of this mode.
Definition: framebuffer.h:64
FBDrawable< 64, 64, 1 > FB64Drawable
Typedef for the FBDrawable instance used in FB64 mode.
Definition: framebuffer.h:325
static unsigned sizeInWords()
Returns the size of this framebuffer's data, in 16-bit words.
Definition: framebuffer.h:101
static uint16_t expand16(unsigned colorIndex)
Given a single color index, return an expanded version where the single color has been replicated to ...
Definition: framebuffer.h:138
void bitmap(UInt2 topLeft, UInt2 size, const uint8_t *data, unsigned stride)
Draw a packed-pixel bitmap, of the same color depth as this framebuffer mode.
Definition: framebuffer.h:286
Definition: array.h:34
_SYSVideoBuffer & videoBuffer()
Return the VideoBuffer associated with this drawable.
Definition: framebuffer.h:308
T y
Vector component Y.
Definition: math.h:490
static unsigned sizeInBytes()
Returns the size of this framebuffer's data, in bytes.
Definition: framebuffer.h:94
void disableKey()
Disable transparency.
Definition: framebuffer.h:436
static unsigned width()
Return the width, in pixels, of this mode.
Definition: framebuffer.h:57
static unsigned bitsPerPixel()
Returns the number of bits per pixel this framebuffer mode uses to store color indices.
Definition: framebuffer.h:87
void setKeyIndex(unsigned index)
Set the palette index of the "key" color.
Definition: framebuffer.h:427
A templatized VRAM accessor for drawing pixel graphics, in one of the cube's supported framebuffer dr...
Definition: framebuffer.h:51
void resizeFB(Int2 pixelSize)
Change the geometry of the framebuffer memory used by this stamp.
Definition: framebuffer.h:350
void fill(unsigned colorIndex)
Fill the entire framebuffer with a specific color index.
Definition: framebuffer.h:215
void fill(UInt2 topLeft, UInt2 size, unsigned colorIndex)
Fill a rectangle of pixels, specified as a top-left corner location and a size.
Definition: framebuffer.h:203
Vector2< T > vec(T x, T y)
Create a Vector2, from a set of (x,y) coordinates.
Definition: math.h:658