The Pedigree Project  0.1
Framebuffer.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 "pedigree/kernel/machine/Framebuffer.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/processor/MemoryRegion.h"
23 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
24 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
25 #include "pedigree/kernel/utilities/utility.h"
26 
27 Framebuffer::Framebuffer() : m_pParent(0), m_FramebufferBase(0), m_bActive(true)
28 {
29  m_Palette = new uint32_t[256];
30 
31  size_t i = 0;
32  for (size_t g = 0; g <= 255; g += 0x33)
33  for (size_t b = 0; b <= 255; b += 0x33)
34  for (size_t r = 0; r <= 255; r += 0x33)
35  m_Palette[i++] = Graphics::createRgb(r, g, b);
36 
37  NOTICE(
38  "Framebuffer: created " << Dec << i << Hex
39  << " entries in the default palette");
40 }
41 
42 Framebuffer::~Framebuffer()
43 {
44 }
45 
46 size_t Framebuffer::getWidth() const
47 {
48  return m_nWidth;
49 }
50 
51 size_t Framebuffer::getHeight() const
52 {
53  return m_nHeight;
54 }
55 
56 Graphics::PixelFormat Framebuffer::getFormat() const
57 {
58  return m_PixelFormat;
59 }
60 
61 bool Framebuffer::getActive() const
62 {
63  return m_bActive;
64 }
65 
66 void Framebuffer::setActive(bool b)
67 {
68  m_bActive = b;
69 }
70 
71 void Framebuffer::setPalette(uint32_t *palette, size_t nEntries)
72 {
73  delete[] m_Palette;
74  m_Palette = new uint32_t[nEntries];
75  MemoryCopy(m_Palette, palette, nEntries * sizeof(uint32_t));
76 
77  NOTICE(
78  "Framebuffer: new palette set with " << Dec << nEntries << Hex
79  << " entries");
80 }
81 
82 uint32_t *Framebuffer::getPalette() const
83 {
84  return m_Palette;
85 }
86 
88 {
89  if (m_pParent)
90  return m_pParent->getRawBuffer();
91  return reinterpret_cast<void *>(m_FramebufferBase);
92 }
93 
95  const void *srcData, Graphics::PixelFormat srcFormat, size_t width,
96  size_t height, uint32_t *pPalette)
97 {
98  if (m_pParent)
99  return m_pParent->createBuffer(
100  srcData, srcFormat, width, height, pPalette);
101  return swCreateBuffer(srcData, srcFormat, width, height, pPalette);
102 }
103 
105 {
106  // if(m_pParent)
107  // m_pParent->destroyBuffer(pBuffer);
108  // else
109  swDestroyBuffer(pBuffer);
110 }
111 
112 void Framebuffer::redraw(size_t x, size_t y, size_t w, size_t h, bool bChild)
113 {
114  if (m_pParent)
115  {
116  // Redraw with parent:
117  // 1. Draw our framebuffer. This will go to the top without
118  // changing intermediate framebuffers.
119  // 2. Pass a redraw up the chain. This will reach the top level
120  // (with modified x/y) and cause our screen region to be redrawn.
121 
125 
126  // If the redraw was not caused by a child, make sure our
127  // framebuffer has precedence over any children.
130  if (!bChild)
131  {
132  if (m_pParent->getFormat() == m_PixelFormat)
133  {
134  Graphics::Buffer buf = bufferFromSelf();
135  m_pParent->draw(
136  &buf, x, y, m_XPos + x, m_YPos + y, w, h, false);
137  // m_pParent->draw(reinterpret_cast<void*>(m_FramebufferBase),
138  // x, y, m_XPos + x, m_YPos + y, w, h, m_PixelFormat,
139  // false);
140  }
141  else
142  {
143  ERROR("Child framebuffer has different pixel format to "
144  "parent!");
145  }
146  }
147 
148  // Now we are a child requesting a redraw, so the parent will not
149  // have precedence over us.
150  m_pParent->redraw(m_XPos + x, m_YPos + y, w, h, true);
151  }
152  else
153  hwRedraw(x, y, w, h);
154 }
155 
157  Graphics::Buffer *pBuffer, size_t srcx, size_t srcy, size_t destx,
158  size_t desty, size_t width, size_t height, bool bLowestCall)
159 {
160  if (m_pParent)
161  m_pParent->blit(
162  pBuffer, srcx, srcy, m_XPos + destx, m_YPos + desty, width, height,
163  false);
164  if (bLowestCall || !m_pParent)
165  swBlit(pBuffer, srcx, srcy, destx, desty, width, height);
166 }
167 
169  void *pBuffer, size_t srcx, size_t srcy, size_t destx, size_t desty,
170  size_t width, size_t height, Graphics::PixelFormat format, bool bLowestCall)
171 {
172  // Draw is implemented as a "create buffer and blit"... so we can
173  // avoid checking for parent here as we don't want to poison the
174  // parent's buffer.
175  swDraw(
176  pBuffer, srcx, srcy, destx, desty, width, height, format, bLowestCall);
177 }
178 
180  size_t x, size_t y, size_t width, size_t height, uint32_t colour,
181  Graphics::PixelFormat format, bool bLowestCall)
182 {
183  if (m_pParent)
184  m_pParent->rect(
185  m_XPos + x, m_YPos + y, width, height, colour, format, false);
186  if (bLowestCall || !m_pParent)
187  swRect(x, y, width, height, colour, format);
188 }
189 
191  size_t srcx, size_t srcy, size_t destx, size_t desty, size_t w, size_t h,
192  bool bLowestCall)
193 {
194  if (m_pParent)
195  m_pParent->copy(
196  m_XPos + srcx, m_YPos + srcy, m_XPos + destx, m_YPos + desty, w, h,
197  false);
198  if (bLowestCall || !m_pParent)
199  swCopy(srcx, srcy, destx, desty, w, h);
200 }
201 
203  size_t x1, size_t y1, size_t x2, size_t y2, uint32_t colour,
204  Graphics::PixelFormat format, bool bLowestCall)
205 {
206  if (m_pParent)
207  m_pParent->line(
208  m_XPos + x1, m_YPos + y1, m_XPos + x2, m_YPos + y2, colour, format,
209  false);
210  if (bLowestCall || !m_pParent)
211  swLine(x1, y1, x2, y2, colour, format);
212 }
213 
215  size_t x, size_t y, uint32_t colour, Graphics::PixelFormat format,
216  bool bLowestCall)
217 {
218  if (m_pParent)
219  m_pParent->setPixel(m_XPos + x, m_YPos + y, colour, format, false);
220  if (bLowestCall || !m_pParent)
221  swSetPixel(x, y, colour, format);
222 }
223 
224 void Framebuffer::setXPos(size_t x)
225 {
226  m_XPos = x;
227 }
228 
229 void Framebuffer::setYPos(size_t y)
230 {
231  m_YPos = y;
232 }
233 
234 void Framebuffer::setWidth(size_t w)
235 {
236  m_nWidth = w;
237 }
238 
239 void Framebuffer::setHeight(size_t h)
240 {
241  m_nHeight = h;
242 }
243 
244 void Framebuffer::setFormat(Graphics::PixelFormat pf)
245 {
246  m_PixelFormat = pf;
247 }
248 
249 void Framebuffer::setBytesPerPixel(size_t b)
250 {
251  m_nBytesPerPixel = b;
252 }
253 
254 uint32_t Framebuffer::getBytesPerPixel() const
255 {
256  return m_nBytesPerPixel;
257 }
258 
259 void Framebuffer::setBytesPerLine(size_t b)
260 {
261  m_nBytesPerLine = b;
262 }
263 
264 uint32_t Framebuffer::getBytesPerLine() const
265 {
266  return m_nBytesPerLine;
267 }
268 
269 void Framebuffer::setParent(Framebuffer *p)
270 {
271  m_pParent = p;
272 }
273 
274 Framebuffer *Framebuffer::getParent() const
275 {
276  return m_pParent;
277 }
278 
279 void Framebuffer::setFramebuffer(uintptr_t p)
280 {
281  m_FramebufferBase = p;
282 }
283 
284 Graphics::Buffer Framebuffer::bufferFromSelf()
285 {
286  Graphics::Buffer ret;
287  ret.base = m_FramebufferBase;
288  ret.width = m_nWidth;
289  ret.height = m_nHeight;
290  ret.format = m_PixelFormat;
291  ret.bytesPerPixel = m_nBytesPerPixel;
292  ret.bufferId = 0;
293  ret.pBacking = 0;
294  return ret;
295 }
296 
298  Graphics::Buffer *pBuffer, size_t srcx, size_t srcy, size_t destx,
299  size_t desty, size_t width, size_t height, bool bLowestCall)
300 {
301  swDraw(pBuffer, srcx, srcy, destx, desty, width, height, bLowestCall);
302 }
303 
305  const void *srcData, Graphics::PixelFormat srcFormat, size_t width,
306  size_t height, uint32_t *pPalette)
307 {
308  if (UNLIKELY(!m_FramebufferBase))
309  return 0;
310  if (UNLIKELY(!(width && height)))
311  return 0;
312 
313  Graphics::PixelFormat destFormat = m_PixelFormat;
314 
315  size_t sourceBytesPerPixel = bytesPerPixel(srcFormat);
316  size_t sourceBytesPerLine = width * sourceBytesPerPixel;
317 
318  size_t destBytesPerPixel = m_nBytesPerPixel;
319  size_t destBytesPerLine = width * destBytesPerPixel;
320 
321  size_t fullBufferSize = height * destBytesPerLine;
322 
323  MemoryRegion *pRegion = new MemoryRegion("sw-framebuffer-buffer");
325  *pRegion, (fullBufferSize / 0x1000) + 1, 0, VirtualAddressSpace::Write);
326 
327  if (!bSuccess)
328  {
329  delete pRegion;
330  return 0;
331  }
332 
333  // Copy the buffer in full
334  void *pAddress = pRegion->virtualAddress();
335  if (((sourceBytesPerPixel == destBytesPerPixel) &&
336  (sourceBytesPerLine == destBytesPerLine)) &&
337  (srcFormat == destFormat))
338  {
339  // Same pixel format and same pixel size. Safe to do a conventional
340  // memcpy. The pixel size check is to handle cases where a buffer may
341  // be, say, 24-bit RGB, and the display driver also 24-bit RGB, but
342  // the display's framebuffer reserves 32 bits for pixels (even though
343  // the actual depth is 24 bits).
344  MemoryCopy(pAddress, srcData, fullBufferSize);
345  }
346  else
347  {
348  // Have to convert and pack each pixel, much slower than memcpy.
349  size_t x, y;
350  for (y = 0; y < height; y++)
351  {
352  for (x = 0; x < width; x++)
353  {
354  size_t sourceOffset =
355  (y * sourceBytesPerLine) + (x * sourceBytesPerPixel);
356  size_t destOffset =
357  (y * destBytesPerLine) + (x * destBytesPerPixel);
358 
359  // We'll always access the beginning of a pixel, which makes
360  // things here much simpler.
361  const uint32_t *pSource = reinterpret_cast<const uint32_t *>(
362  adjust_pointer(srcData, sourceOffset));
363 
364  uint32_t transform = 0;
365  if (srcFormat == Graphics::Bits8_Idx)
366  {
367  uint32_t source = pPalette[(*pSource) & 0xFF];
368  Graphics::convertPixel(
369  source, Graphics::Bits24_Bgr, transform, destFormat);
370  }
371  else
372  {
373  Graphics::convertPixel(
374  *pSource, srcFormat, transform, destFormat);
375  }
376 
377  if (destBytesPerPixel == 4)
378  {
379  uint32_t *pDest = reinterpret_cast<uint32_t *>(
380  adjust_pointer(pAddress, destOffset));
381 
382  if (sourceBytesPerPixel == 3)
383  transform &= 0xFFFFFF;
384  else if (sourceBytesPerPixel == 2)
385  transform &= 0xFFFF;
386 
387  *pDest = transform;
388  }
389  else if (destBytesPerPixel == 3)
390  {
391  // Handle existing data after this byte if it exists
392  uint32_t *pDest = reinterpret_cast<uint32_t *>(
393  adjust_pointer(pAddress, destOffset));
394  *pDest = (*pDest & 0xFF000000) | (transform & 0xFFFFFF);
395  }
396  else if (destBytesPerPixel == 2)
397  {
398  uint16_t *pDest = reinterpret_cast<uint16_t *>(
399  adjust_pointer(pAddress, destOffset));
400  *pDest = transform & 0xFFFF;
401  }
402  else if (destBytesPerPixel == 1)
403  {
405  }
406  }
407  }
408  }
409 
410  Graphics::Buffer *pBuffer = new Graphics::Buffer;
411  pBuffer->base = reinterpret_cast<uintptr_t>(pRegion->virtualAddress());
412  pBuffer->width = width;
413  pBuffer->height = height;
414  pBuffer->format = m_PixelFormat;
415  pBuffer->bytesPerPixel = destBytesPerPixel;
416  pBuffer->bufferId = 0;
417  pBuffer->pBacking = reinterpret_cast<void *>(pRegion);
418 
419  return pBuffer;
420 }
421 
422 void Framebuffer::swDestroyBuffer(Graphics::Buffer *pBuffer)
423 {
424  if (pBuffer)
425  {
426  if (pBuffer->base)
427  {
428  MemoryRegion *pRegion =
429  reinterpret_cast<MemoryRegion *>(pBuffer->pBacking);
430  delete pRegion; // Unmaps the memory as well
431  }
432  delete pBuffer;
433  }
434 }
435 
437  Graphics::Buffer *pBuffer, size_t srcx, size_t srcy, size_t destx,
438  size_t desty, size_t width, size_t height)
439 {
440  if (UNLIKELY(!m_FramebufferBase))
441  return;
442  if (UNLIKELY(!(width && height)))
443  return;
444  if (UNLIKELY(!pBuffer))
445  return;
446 
447  size_t bytesPerLine = m_nBytesPerLine;
448  size_t destBytesPerPixel = m_nBytesPerPixel;
449 
450  size_t sourceBytesPerPixel = pBuffer->bytesPerPixel;
451  size_t sourceBytesPerLine = pBuffer->width * destBytesPerPixel;
452 
453  // Sanity check and clip
454  if ((srcx > pBuffer->width) || (srcy > pBuffer->height))
455  return;
456  if ((destx > m_nWidth) || (desty > m_nHeight))
457  return;
458  if ((srcx + width) > pBuffer->width)
459  width = (srcx + width) - pBuffer->width;
460  if ((srcy + height) > pBuffer->height)
461  height = (srcy + height) - pBuffer->height;
462  if ((destx + width) > m_nWidth)
463  width = m_nWidth - destx; // (destx + width) - m_nWidth;
464  if ((desty + height) > m_nHeight)
465  height = m_nHeight - desty; // (desty + height) - m_nHeight;
466 
468 
469  void *pSrc = reinterpret_cast<void *>(pBuffer->base);
470 
471  // Blit across the width of the screen? How handy!
472  if (UNLIKELY((srcx == destx) && (srcx == 0) && (width == m_nWidth)))
473  {
474  size_t sourceBufferOffset = (srcy * sourceBytesPerLine);
475  size_t frameBufferOffset = (desty * bytesPerLine);
476 
477  void *dest =
478  reinterpret_cast<void *>(m_FramebufferBase + frameBufferOffset);
479  void *src = adjust_pointer(pSrc, sourceBufferOffset);
480 
481  MemoryCopy(dest, src, bytesPerLine * height);
482  }
483  else
484  {
485  // Line-by-line copy
486  for (size_t y1 = desty, y2 = srcy; y1 < (desty + height); y1++, y2++)
487  {
488  size_t sourceBufferOffset =
489  (y2 * sourceBytesPerLine) + (srcx * sourceBytesPerPixel);
490  size_t frameBufferOffset =
491  (y1 * bytesPerLine) + (destx * destBytesPerPixel);
492 
493  void *dest =
494  reinterpret_cast<void *>(m_FramebufferBase + frameBufferOffset);
495  void *src = adjust_pointer(pSrc, sourceBufferOffset);
496 
497  MemoryCopy(dest, src, width * destBytesPerPixel);
498  }
499  }
500 }
501 
503  size_t x, size_t y, size_t width, size_t height, uint32_t colour,
504  Graphics::PixelFormat format)
505 {
506  if (UNLIKELY(!m_FramebufferBase))
507  return;
508  if (UNLIKELY(!(width && height)))
509  return;
510 
511  // Sanity check and clip
512  if ((x > m_nWidth) || (y > m_nHeight))
513  return;
514  if (width > m_nWidth)
515  width = m_nWidth;
516  if (height > m_nHeight)
517  height = m_nHeight;
518  if ((x + width) > m_nWidth)
519  width = (x + width) - m_nWidth;
520  if ((y + height) > m_nHeight)
521  height = (y + height) - m_nHeight;
522 
523  uint32_t transformColour = 0;
524  if (format == Graphics::Bits8_Idx)
525  {
526  uint32_t source = m_Palette[colour & 0xFF];
527  Graphics::convertPixel(
528  source, Graphics::Bits24_Bgr, transformColour, m_PixelFormat);
529  }
530  else
531  Graphics::convertPixel(colour, format, transformColour, m_PixelFormat);
532 
533  size_t bytesPerPixel = m_nBytesPerPixel;
534  size_t bytesPerLine = m_nBytesPerLine;
535 
536  // Can we just do an easy memset?
537  if (UNLIKELY((!x) && (width == m_nWidth)))
538  {
539  size_t frameBufferOffset = (y * bytesPerLine) + (x * bytesPerPixel);
540 
541  void *dest =
542  reinterpret_cast<void *>(m_FramebufferBase + frameBufferOffset);
543 
544  size_t copySize = (bytesPerLine * height);
545  if (bytesPerPixel == 4)
546  {
547  if ((copySize % 8) == 0) // QWORD boundary
548  {
549  uint64_t val = (static_cast<uint64_t>(transformColour) << 32) |
550  transformColour;
551  QuadWordSet(dest, val, copySize / 8);
552  }
553  else
554  DoubleWordSet(dest, transformColour, copySize / 4);
555  }
556  else if (bytesPerPixel == 3)
557  {
558  // 24-bit has to set three bytes at a time and leave the top byte
559  // untouched. Painful.
560  for (size_t i = 0; i < (copySize / 3); i++)
561  {
562  uint32_t *p = reinterpret_cast<uint32_t *>(
563  m_FramebufferBase + frameBufferOffset + (i * 3));
564  *p = (*p & 0xFF000000) | transformColour;
565  }
566  }
567  else if (bytesPerPixel == 2)
568  {
569  if ((copySize % 8) == 0) // QWORD boundary
570  {
571  uint64_t val = (static_cast<uint64_t>(transformColour) << 48) |
572  (static_cast<uint64_t>(transformColour) << 32) |
573  (transformColour << 16) | transformColour;
574  QuadWordSet(dest, val, copySize / 8);
575  }
576  else if ((copySize % 4) == 0) // DWORD boundary
577  {
578  uint32_t val = (transformColour << 16) | transformColour;
579  DoubleWordSet(dest, val, copySize / 4);
580  }
581  else
582  WordSet(dest, transformColour, copySize / 2);
583  }
584  else
585  ByteSet(dest, transformColour, (bytesPerLine * height));
586  }
587  else
588  {
589  // Line-by-line fill
590  for (size_t desty = y; desty < (y + height); desty++)
591  {
592  size_t frameBufferOffset =
593  (desty * bytesPerLine) + (x * bytesPerPixel);
594 
595  void *dest =
596  reinterpret_cast<void *>(m_FramebufferBase + frameBufferOffset);
597 
598  size_t copySize = width * bytesPerPixel;
599  if (bytesPerPixel == 4)
600  {
601  if ((copySize % 8) == 0) // QWORD boundary
602  {
603  uint64_t val =
604  (static_cast<uint64_t>(transformColour) << 32) |
605  transformColour;
606  QuadWordSet(dest, val, copySize / 8);
607  }
608  else
609  DoubleWordSet(dest, transformColour, copySize / 4);
610  }
611  else if (bytesPerPixel == 3)
612  {
613  // 24-bit has to set three bytes at a time and leave the top
614  // byte untouched. Painful.
615  for (size_t i = 0; i < (copySize / 3); i++)
616  {
617  uint32_t *p = reinterpret_cast<uint32_t *>(
618  m_FramebufferBase + frameBufferOffset + (i * 3));
619  *p = (*p & 0xFF000000) | transformColour;
620  }
621  }
622  else if (bytesPerPixel == 2)
623  {
624  if ((copySize % 8) == 0) // QWORD boundary
625  {
626  uint64_t val =
627  (static_cast<uint64_t>(transformColour) << 48) |
628  (static_cast<uint64_t>(transformColour) << 32) |
629  (transformColour << 16) | transformColour;
630  QuadWordSet(dest, val, copySize / 8);
631  }
632  else if ((copySize % 4) == 0) // DWORD boundary
633  {
634  uint32_t val = (transformColour << 16) | transformColour;
635  DoubleWordSet(dest, val, copySize / 4);
636  }
637  else
638  WordSet(dest, transformColour, copySize / 2);
639  }
640  else
641  ByteSet(dest, transformColour, (width * bytesPerPixel));
642  }
643  }
644 }
645 
647  size_t srcx, size_t srcy, size_t destx, size_t desty, size_t w, size_t h)
648 {
649  if (UNLIKELY(!m_FramebufferBase))
650  return;
651  if (UNLIKELY(!(w && h)))
652  return;
653  if (UNLIKELY((srcx == destx) && (srcy == desty)))
654  return;
655 
656  // Sanity check and clip
657  if ((srcx > m_nWidth) || (srcy > m_nHeight))
658  return;
659  if ((destx > m_nWidth) || (desty > m_nHeight))
660  return;
661  if ((srcx + w) > m_nWidth)
662  w = (srcx + w) - m_nWidth;
663  if ((srcy + h) > m_nHeight)
664  h = (srcy + h) - m_nHeight;
665  if ((destx + w) > m_nWidth)
666  w = (destx + w) - m_nWidth;
667  if ((desty + h) > m_nHeight)
668  h = (desty + h) - m_nHeight;
669 
670  if ((srcx == destx) && (srcy == desty))
671  return;
672  if (!(w && h))
673  return;
674 
675  size_t bytesPerLine = m_nBytesPerLine;
676  size_t bytesPerPixel = m_nBytesPerPixel;
678 
679  // Easy memcpy?
680  if (UNLIKELY(((!srcx) && (!destx)) && (w == m_nWidth)))
681  {
682  size_t frameBufferOffsetSrc =
683  (srcy * bytesPerLine) + (srcx * bytesPerPixel);
684  size_t frameBufferOffsetDest =
685  (desty * bytesPerLine) + (destx * bytesPerPixel);
686 
687  void *dest =
688  reinterpret_cast<void *>(m_FramebufferBase + frameBufferOffsetDest);
689  void *src =
690  reinterpret_cast<void *>(m_FramebufferBase + frameBufferOffsetSrc);
691 
692  MemoryCopy(dest, src, h * bytesPerLine);
693  }
694  else
695  {
696  // Not so easy, but still not too hard
697  for (size_t yoff = 0; yoff < h; yoff++)
698  {
699  size_t frameBufferOffsetSrc =
700  ((srcy + yoff) * bytesPerLine) + (srcx * bytesPerPixel);
701  size_t frameBufferOffsetDest =
702  ((desty + yoff) * bytesPerLine) + (destx * bytesPerPixel);
703 
704  void *dest = reinterpret_cast<void *>(
705  m_FramebufferBase + frameBufferOffsetDest);
706  void *src = reinterpret_cast<void *>(
707  m_FramebufferBase + frameBufferOffsetSrc);
708 
709  MemoryCopy(dest, src, w * bytesPerPixel);
710  }
711  }
712 }
713 
714 void Framebuffer::swLine(
715  size_t x1, size_t y1, size_t x2, size_t y2, uint32_t colour,
716  Graphics::PixelFormat format)
717 {
718  if (UNLIKELY(!m_FramebufferBase))
719  return;
720 
721  // Clip co-ordinates where necessary
722  if (x1 > m_nWidth)
723  x1 = m_nWidth;
724  if (x2 > m_nWidth)
725  x2 = m_nWidth;
726  if (y1 > m_nHeight)
727  y1 = m_nHeight;
728  if (y2 > m_nHeight)
729  y2 = m_nHeight;
730 
731  // NOTICE("swLine(" << Dec << x1 << ", " << y1 << " -> " << x2 << ", " << y2
732  // << Hex << ")");
733 
734  if (UNLIKELY((x1 == x2) && (y1 == y2)))
735  return;
736 
737  uint32_t transformColour = 0;
738  if (format == Graphics::Bits8_Idx)
739  {
740  uint32_t source = m_Palette[colour & 0xFF];
741  Graphics::convertPixel(
742  source, Graphics::Bits24_Bgr, transformColour, m_PixelFormat);
743  }
744  else
745  Graphics::convertPixel(colour, format, transformColour, m_PixelFormat);
746 
747  // Special cases
748  if (x1 == x2) // Vertical line
749  {
750  if (y1 > y2)
751  swap(y1, y2);
752  for (size_t y = y1; y < y2; y++)
753  setPixel(x1, y, transformColour, m_PixelFormat);
754  return;
755  }
756  else if (y1 == y2)
757  {
758  if (x1 > x2)
759  swap(x1, x2);
760  for (size_t x = x1; x < x2; x++)
761  setPixel(x, y1, transformColour, m_PixelFormat);
762  return;
763  }
764 
765  // Bresenham's algorithm, referred to Computer Graphics, C Version (2nd
766  // Edition) from 1997, by D. Hearn and M. Pauline Baker (page 88)
767  // http://www.amazon.com/Computer-Graphics-C-Version-2nd/dp/0135309247
768 
769  ssize_t dx = static_cast<ssize_t>(x2) - static_cast<ssize_t>(x1);
770  ssize_t dy = static_cast<ssize_t>(y2) - static_cast<ssize_t>(y1);
771  ssize_t p = 2 * (dy - dx);
772  ssize_t x, y, xEnd;
773 
774  if (x1 > x2)
775  {
776  x = x2;
777  y = y2;
778  xEnd = x1;
779  }
780  else
781  {
782  x = x1;
783  y = y1;
784  xEnd = x2;
785  }
786 
787  setPixel(x, y, transformColour, m_PixelFormat);
788 
789  while (x < xEnd)
790  {
791  x++;
792  if (p < 0)
793  p += (dy * 2);
794  else
795  {
796  y++;
797  p += 2 * (dy - dx);
798  }
799 
800  setPixel(x, y, transformColour, m_PixelFormat);
801  }
802 }
803 
805  size_t x, size_t y, uint32_t colour, Graphics::PixelFormat format)
806 {
807  if (UNLIKELY(!m_FramebufferBase))
808  return;
809 
810  if (x > m_nWidth)
811  x = m_nWidth;
812  if (y > m_nHeight)
813  y = m_nHeight;
814 
815  size_t bytesPerPixel = m_nBytesPerPixel;
816  size_t bytesPerLine = m_nBytesPerLine;
817 
818  uint32_t transformColour = 0;
819  if (format == Graphics::Bits8_Idx)
820  {
821  uint32_t source = m_Palette[colour & 0xFF];
822  Graphics::convertPixel(
823  source, Graphics::Bits24_Bgr, transformColour, m_PixelFormat);
824  }
825  else
826  Graphics::convertPixel(colour, format, transformColour, m_PixelFormat);
827 
828  size_t frameBufferOffset = (y * bytesPerLine) + (x * bytesPerPixel);
829 
830  if (bytesPerPixel == 4)
831  {
832  uint32_t *pDest =
833  reinterpret_cast<uint32_t *>(m_FramebufferBase + frameBufferOffset);
834  *pDest = transformColour;
835  }
836  else if (bytesPerPixel == 3)
837  {
838  // Handle existing data after this byte if it exists
839  uint32_t *pDest =
840  reinterpret_cast<uint32_t *>(m_FramebufferBase + frameBufferOffset);
841  *pDest = (*pDest & 0xFF000000) | (transformColour & 0xFFFFFF);
842  }
843  else if (bytesPerPixel == 2)
844  {
845  uint16_t *pDest =
846  reinterpret_cast<uint16_t *>(m_FramebufferBase + frameBufferOffset);
847  *pDest = transformColour & 0xFFFF;
848  }
849  else if (bytesPerPixel == 1)
850  {
852  }
853 }
854 
855 void Framebuffer::swDraw(
856  void *pBuffer, size_t srcx, size_t srcy, size_t destx, size_t desty,
857  size_t width, size_t height, Graphics::PixelFormat format, bool bLowestCall)
858 {
859  // Potentially inefficient use of RAM and VRAM, but best way to avoid
860  // redundant copies of code lying around.
861  Graphics::Buffer *p =
862  createBuffer(pBuffer, format, srcx + width, srcy + height, m_Palette);
863  if (!p)
864  {
865  return;
866  }
867  blit(p, srcx, srcy, destx, desty, width, height, bLowestCall);
868  destroyBuffer(p);
869 }
870 
871 void Framebuffer::swDraw(
872  Graphics::Buffer *pBuffer, size_t srcx, size_t srcy, size_t destx,
873  size_t desty, size_t width, size_t height, bool bLowestCall)
874 {
875  blit(pBuffer, srcx, srcy, destx, desty, width, height, bLowestCall);
876 }
877 
878 void Framebuffer::hwRedraw(size_t x, size_t y, size_t w, size_t h)
879 {
880 }
virtual void copy(size_t srcx, size_t srcy, size_t destx, size_t desty, size_t w, size_t h, bool bLowestCall=true)
Definition: Framebuffer.cc:190
static PhysicalMemoryManager & instance()
void swCopy(size_t srcx, size_t srcy, size_t destx, size_t desty, size_t w, size_t h)
Definition: Framebuffer.cc:646
uintptr_t base
Base of this buffer in memory. For internal use only.
Graphics::Buffer * swCreateBuffer(const void *srcData, Graphics::PixelFormat srcFormat, size_t width, size_t height, uint32_t *pPalette)
Definition: Framebuffer.cc:304
virtual void blit(Graphics::Buffer *pBuffer, size_t srcx, size_t srcy, size_t destx, size_t desty, size_t width, size_t height, bool bLowestCall=true)
Definition: Framebuffer.cc:156
virtual void hwRedraw(size_t x=~0UL, size_t y=~0UL, size_t w=~0UL, size_t h=~0UL)
Inherited by drivers that provide a hardware redraw function.
Definition: Framebuffer.cc:878
void swRect(size_t x, size_t y, size_t width, size_t height, uint32_t colour, Graphics::PixelFormat format)
Definition: Framebuffer.cc:502
void swBlit(Graphics::Buffer *pBuffer, size_t srcx, size_t srcy, size_t destx, size_t desty, size_t width, size_t height)
Definition: Framebuffer.cc:436
size_t bufferId
Buffer ID, for easy identification within drivers.
virtual void destroyBuffer(Graphics::Buffer *pBuffer)
Definition: Framebuffer.cc:104
virtual void * getRawBuffer() const
Definition: Framebuffer.cc:87
virtual void rect(size_t x, size_t y, size_t width, size_t height, uint32_t colour, Graphics::PixelFormat format=Graphics::Bits32_Argb, bool bLowestCall=true)
Definition: Framebuffer.cc:179
void redraw(size_t x=~0UL, size_t y=~0UL, size_t w=~0UL, size_t h=~0UL, bool bChild=false)
Definition: Framebuffer.cc:112
#define NOTICE(text)
Definition: Log.h:74
Special memory entity in the kernel&#39;s virtual address space.
Definition: MemoryRegion.h:35
Definition: Log.h:136
virtual void draw(void *pBuffer, size_t srcx, size_t srcy, size_t destx, size_t desty, size_t width, size_t height, Graphics::PixelFormat format=Graphics::Bits32_Argb, bool bLowestCall=true)
Definition: Framebuffer.cc:168
void swSetPixel(size_t x, size_t y, uint32_t colour, Graphics::PixelFormat format=Graphics::Bits32_Argb)
Definition: Framebuffer.cc:804
Abstracts the system&#39;s framebuffer offering.
void setPixel(size_t x, size_t y, uint32_t colour, Graphics::PixelFormat format=Graphics::Bits32_Argb, bool bLowestCall=true)
Definition: Framebuffer.cc:214
void setPalette(uint32_t *palette, size_t nEntries)
Definition: Framebuffer.cc:71
size_t width
Width of the buffer in pixels.
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
void * virtualAddress() const
Definition: MemoryRegion.cc:39
#define ERROR(text)
Definition: Log.h:82
Definition: Log.h:138
size_t height
Height of the buffer in pixels.
virtual void line(size_t x1, size_t y1, size_t x2, size_t y2, uint32_t colour, Graphics::PixelFormat format=Graphics::Bits32_Argb, bool bLowestCall=true)
Definition: Framebuffer.cc:202
virtual Graphics::Buffer * createBuffer(const void *srcData, Graphics::PixelFormat srcFormat, size_t width, size_t height, uint32_t *pPalette=0)
Definition: Framebuffer.cc:94
size_t bytesPerPixel
Number of bytes per pixel (as it may be different to the format).