20 #include "VbeDisplay.h" 21 #include "modules/system/config/Config.h" 22 #include "pedigree/kernel/Log.h" 23 #include "pedigree/kernel/graphics/Graphics.h" 24 #include "pedigree/kernel/machine/Framebuffer.h" 25 #include "pedigree/kernel/machine/Machine.h" 26 #include "pedigree/kernel/machine/Vga.h" 27 #include "pedigree/kernel/machine/x86_common/Bios.h" 28 #include "pedigree/kernel/processor/MemoryMappedIo.h" 29 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 30 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 31 #include "pedigree/kernel/utilities/Iterator.h" 32 #include "pedigree/kernel/utilities/String.h" 33 #include "pedigree/kernel/utilities/Vector.h" 34 #include "pedigree/kernel/utilities/utility.h" 39 static uintptr_t g_Framebuffer;
40 static size_t g_FbSize;
42 VbeDisplay::VbeDisplay()
43 : m_VbeVersion(), m_ModeList(), m_Mode(), m_pFramebuffer(), m_Buffers(),
44 m_SpecialisedMode(Mode_Generic), m_Allocator()
48 VbeDisplay::VbeDisplay(
50 size_t vidMemSz,
size_t displayNum)
51 :
Display(p), m_VbeVersion(version), m_ModeList(sms), m_Mode(),
52 m_pFramebuffer(0), m_Buffers(), m_SpecialisedMode(Mode_Generic),
56 str.Format(
"DELETE FROM 'display_modes' where display_id = %d", displayNum);
60 FATAL(
"VBE: Couldn't get a result.");
73 it != m_ModeList.end(); it++)
76 "INSERT INTO 'display_modes' VALUES (NULL, %d,%d,%d,%d,%d,%d)",
77 (*it)->id, displayNum, (*it)->width, (*it)->height, (*it)->pf.nBpp,
79 pR = Config::instance().
query(str);
87 fbAddr = (*it)->framebuffer;
92 m_Allocator.free(0, vidMemSz);
95 bool bFramebufferFound =
false;
99 uintptr_t address = (*it)->m_Address;
100 size_t size = (*it)->m_Size;
101 if (address <= fbAddr && (address + size) > fbAddr)
104 m_pFramebufferRawAddress = (*it);
105 bFramebufferFound =
true;
110 if (!bFramebufferFound)
111 ERROR(
"No PCI MMIO region found for the desired video mode.");
114 VbeDisplay::~VbeDisplay()
120 return m_pFramebuffer->virtualAddress();
146 it != m_ModeList.end(); it++)
148 if ((*it)->id == modeId)
156 ERROR(
"Screenmode not found: " << modeId);
167 if (m_Mode.pf.
nBpp == 16 && m_Mode.pf.
pRed == 11 && m_Mode.pf.
mRed == 5 &&
171 m_Mode.pf2 = Graphics::Bits16_Rgb565;
172 m_SpecialisedMode = Mode_16bpp_5r6g5b;
175 m_Mode.pf.
nBpp == 16 && m_Mode.pf.
pRed == 10 && m_Mode.pf.
mRed == 5 &&
179 m_Mode.pf2 = Graphics::Bits16_Rgb555;
181 else if (m_Mode.pf.
nBpp == 24 && m_Mode.pf.
pBlue == 0)
183 m_Mode.pf2 = Graphics::Bits24_Rgb;
184 m_SpecialisedMode = Mode_24bpp_8r8g8b;
186 else if (m_Mode.pf.
nBpp == 24 && m_Mode.pf.
pBlue > 0)
189 m_Mode.pf2 = Graphics::Bits24_Bgr;
191 else if (m_Mode.pf.
nBpp == 32)
193 m_Mode.pf2 = Graphics::Bits32_Argb;
197 m_Mode.pf2 = Graphics::Bits16_Argb;
198 m_SpecialisedMode = Mode_Generic;
201 m_Mode.bytesPerPixel = bytesPerPixel(m_Mode.pf2);
202 m_Mode.bytesPerLine = m_Mode.bytesPerPixel * m_Mode.width;
206 it != m_Buffers.end(); it++)
208 Buffer *pBuf = it.value();
222 ERROR(
"VBE: Set mode failed! (mode " <<
Hex << m_Mode.id <<
")");
225 NOTICE(
"VBE: Set mode " << m_Mode.id);
231 m_pLogicalFramebuffer->setWidth(m_Mode.width);
232 m_pLogicalFramebuffer->setHeight(m_Mode.height);
233 m_pLogicalFramebuffer->setBytesPerPixel(m_Mode.bytesPerPixel);
234 m_pLogicalFramebuffer->setBytesPerLine(m_Mode.bytesPerLine);
235 m_pLogicalFramebuffer->setFormat(m_Mode.pf2);
236 m_pLogicalFramebuffer->setXPos(0);
237 m_pLogicalFramebuffer->setYPos(0);
238 m_pLogicalFramebuffer->setParent(0);
240 m_pFramebufferRawAddress->map(
241 (m_Mode.height * m_Mode.bytesPerLine) + m_Mode.width,
true,
true);
242 m_pLogicalFramebuffer->setFramebuffer(
243 reinterpret_cast<uintptr_t>(m_pFramebuffer->virtualAddress()));
246 g_ScreenMode = m_Mode;
248 reinterpret_cast<uintptr_t
>(m_pFramebuffer->virtualAddress());
249 g_FbSize = m_pFramebuffer->size();
259 size_t sz = m_Mode.width * m_Mode.height *
sizeof(
rgb_t);
269 ERROR(
"VbeDisplay::newBuffer: allocateRegion failed!");
272 pBuffer->pBackbuffer =
275 sz = m_Mode.width * m_Mode.height * (m_Mode.pf.
nBpp / 8);
284 ERROR(
"VbeDisplay::newBuffer: allocateRegion failed! (1)");
287 pBuffer->pFbBackbuffer =
290 m_Buffers.insert(pBuffer->pBackbuffer, pBuffer);
292 return pBuffer->pBackbuffer;
295 void VbeDisplay::setCurrentBuffer(
rgb_t *pBuffer)
297 Buffer *pBuf = m_Buffers.lookup(pBuffer);
298 if (!pBuf || !pBuf->valid)
301 "VbeDisplay: Bad buffer:" << reinterpret_cast<uintptr_t>(pBuffer));
307 m_Mode.width * m_Mode.height * (m_Mode.pf.
nBpp / 8));
310 void VbeDisplay::updateBuffer(
311 rgb_t *pBuffer,
size_t x1,
size_t y1,
size_t x2,
size_t y2)
313 Buffer *pBuf = m_Buffers.lookup(pBuffer);
314 if (!pBuf || !pBuf->valid)
317 "VbeDisplay: updateBuffer: Bad buffer:" 318 << reinterpret_cast<uintptr_t>(pBuffer));
324 if (x2 == ~0UL || x2 >= m_Mode.width)
325 x2 = m_Mode.width - 1;
328 if (y2 == ~0UL || y2 >= m_Mode.height)
329 y2 = m_Mode.height - 1;
331 if (m_SpecialisedMode == Mode_16bpp_5r6g5b)
335 unsigned int pitch = m_Mode.width;
337 for (y = y1; y <= y2; y++)
339 for (x = x1; x < x2; x++)
341 rgb_t *pRgb = pBuffer + pitch * y + x;
342 unsigned short r = (pRgb->r >> 3);
343 unsigned short g = (pRgb->g >> 2);
344 unsigned short b = (pRgb->b >> 3);
345 unsigned short a = (r << 11) | (g << 5) | b;
346 reinterpret_cast<uint16_t *
>(
347 pBuf->pFbBackbuffer)[pitch * y + x] = a;
356 if (m_SpecialisedMode == Mode_24bpp_8r8g8b)
358 unsigned int x, y, i;
361 uint8_t *pFb2 = pBuf->pFbBackbuffer;
363 for (y = y1; y <= y2; y++)
365 for (x = x1; x < x2; x++)
367 rgb_t *pRgb = pBuffer + m_Mode.width * y + x;
368 i = (y * m_Mode.width + x) * 3;
369 pFb[i + 0] = pRgb->b;
370 pFb[i + 1] = pRgb->g;
371 pFb[i + 2] = pRgb->r;
372 pFb2[i + 0] = pRgb->b;
373 pFb2[i + 1] = pRgb->g;
374 pFb2[i + 2] = pRgb->r;
381 size_t bytesPerPixel = m_Mode.pf.
nBpp / 8;
384 for (
size_t y = y1; y <= y2; y++)
386 for (
size_t x = x1; x <= x2; x++)
388 size_t i = y * m_Mode.width + x;
391 reinterpret_cast<uintptr_t>(pBuf->pFbBackbuffer));
396 y * m_Mode.pf.
nPitch + x1 * bytesPerPixel,
397 pBuf->pFbBackbuffer + y * m_Mode.pf.
nPitch + x1 * bytesPerPixel,
398 (x2 - x1) * bytesPerPixel);
402 void VbeDisplay::killBuffer(
rgb_t *pBuffer)
404 Buffer *pBuf = m_Buffers.lookup(pBuffer);
408 "VbeDisplay: killBuffer: Bad buffer:" 409 << reinterpret_cast<uintptr_t>(pBuffer));
417 m_Buffers.remove(pBuffer);
420 void VbeDisplay::bitBlit(
421 rgb_t *pBuffer,
size_t fromX,
size_t fromY,
size_t toX,
size_t toY,
422 size_t width,
size_t height)
424 Buffer *pBuf = m_Buffers.lookup(pBuffer);
425 if (!pBuf || !pBuf->valid)
428 "VbeDisplay: bitBlit: Bad buffer:" 429 << reinterpret_cast<uintptr_t>(pBuffer));
433 size_t bytesPerPixel = m_Mode.pf.
nBpp / 8;
435 uint8_t *pFb = pBuf->pFbBackbuffer;
441 ssize_t increment = 1;
449 if (toX == 0 && fromX == 0 && width == m_Mode.width)
451 size_t to = toY * m_Mode.width;
452 size_t from = fromY * m_Mode.width;
453 size_t sz = width * height;
454 size_t extent_s, extent_e;
458 extent_e = from + sz - extent_s;
463 extent_e = to + sz - extent_s;
466 MemoryCopy(&pBuffer[to], &pBuffer[from], sz *
sizeof(
rgb_t));
468 &pFb[to * bytesPerPixel], &pFb[from * bytesPerPixel],
472 extent_s * bytesPerPixel,
473 pBuf->pFbBackbuffer + extent_s * bytesPerPixel,
474 extent_e * bytesPerPixel);
479 for (
size_t y = min; y < max; y += increment)
481 size_t to = (y + toY) * m_Mode.width + toX;
482 size_t from = (y + fromY) * m_Mode.width + fromX;
483 MemoryCopy(&pBuffer[to], &pBuffer[from], width *
sizeof(
rgb_t));
485 &pFb[to * bytesPerPixel], &pFb[from * bytesPerPixel],
486 width * bytesPerPixel);
490 pBuf->pFbBackbuffer + to * bytesPerPixel,
491 width * bytesPerPixel);
497 rgb_t *pBuffer,
size_t x,
size_t y,
size_t width,
size_t height,
500 Buffer *pBuf = m_Buffers.lookup(pBuffer);
501 if (!pBuf || !pBuf->valid)
504 "VbeDisplay: fillRect: Bad buffer:" 505 << reinterpret_cast<uintptr_t>(pBuffer));
510 uint8_t *pFb2 = pBuf->pFbBackbuffer;
512 size_t compiledColour = 0;
513 if (m_SpecialisedMode == Mode_16bpp_5r6g5b)
515 compiledColour = ((colour.r >> 3) << 11) | ((colour.g >> 2) << 5) |
516 ((colour.b >> 3) << 0);
517 for (
size_t i = y; i < y + height; i++)
520 &pBuffer[i * m_Mode.width + x],
521 *reinterpret_cast<uint32_t *>(&colour), width);
523 &pFb[(i * m_Mode.width + x) * 2],
524 static_cast<uint16_t>(compiledColour), width);
526 &pFb2[(i * m_Mode.width + x) * 2],
527 static_cast<uint16_t>(compiledColour), width);
533 packColour(colour, 0, reinterpret_cast<uintptr_t>(&compiledColour));
537 for (
size_t i = y; i < y + height; i++)
539 for (
size_t j = x; j < x + width; j++)
541 pBuffer[i * m_Mode.width + j] = colour;
542 switch (m_Mode.pf.
nBpp)
547 uint16_t *pFb16 =
reinterpret_cast<uint16_t *
>(pFb);
548 uint16_t *pFb162 =
reinterpret_cast<uint16_t *
>(pFb2);
549 pFb16[i * m_Mode.width + j] = compiledColour & 0xFFFF;
550 pFb162[i * m_Mode.width + j] = compiledColour & 0xFFFF;
554 pFb[(i * m_Mode.width + j) * 3 + 0] = colour.b;
555 pFb[(i * m_Mode.width + j) * 3 + 1] = colour.g;
556 pFb[(i * m_Mode.width + j) * 3 + 2] = colour.r;
557 pFb2[(i * m_Mode.width + j) * 3 + 0] = colour.b;
558 pFb2[(i * m_Mode.width + j) * 3 + 1] = colour.g;
559 pFb2[(i * m_Mode.width + j) * 3 + 2] = colour.r;
562 WARNING(
"VbeDisplay: Pixel format not handled in " 569 void VbeDisplay::packColour(
rgb_t colour,
size_t idx, uintptr_t pFb)
573 uint8_t r = colour.r;
574 uint8_t g = colour.g;
575 uint8_t b = colour.b;
578 uint8_t range = 1 << pf.
mRed;
581 r = (r * range) / 256;
586 g = (g * range) / 256;
588 range = 1 << pf.
mBlue;
591 b = (b * range) / 256;
594 uint32_t c = 0 | (
static_cast<uint32_t
>(r) << pf.
pRed) |
595 (
static_cast<uint32_t
>(g) << pf.
pGreen) |
596 (
static_cast<uint32_t
>(b) << pf.
pBlue);
603 uint16_t *pFb16 =
reinterpret_cast<uint16_t *
>(pFb);
609 rgb_t *pFbRgb =
reinterpret_cast<rgb_t *
>(pFb);
610 pFbRgb[idx].r =
static_cast<uint32_t
>(b);
611 pFbRgb[idx].g =
static_cast<uint32_t
>(g);
612 pFbRgb[idx].b =
static_cast<uint32_t
>(r);
617 uint32_t *pFb32 =
reinterpret_cast<uint32_t *
>(pFb);
static size_t getPageSize() PURE
virtual void * getFramebuffer()
static PhysicalMemoryManager & instance()
virtual bool getPixelFormat(Display::PixelFormat &pPf)
virtual bool setScreenMode(Display::ScreenMode sm)
A vector / dynamic array.
void executeInterrupt(int interrupt)
virtual void fillRectangle(rgb_t *pBuffer, size_t x, size_t y, size_t width, size_t height, rgb_t colour)
virtual Vga * getVga(size_t n)=0
virtual bool setScreenMode(Display::ScreenMode sm)
virtual bool setMode(int mode)=0
virtual rgb_t * newBuffer()
static const size_t Write
Result * query(const char *sql)
bool succeeded()
Returns true if the result is valid, false if there was an error.
virtual void * getFramebuffer()
Vector< Address * > m_Addresses
void * virtualAddress() const
virtual bool getScreenModes(List< Display::ScreenMode * > &sms)
An iterator applicable for many data structures.
std::string errorMessage(size_t buffSz=256)
Returns the error message.
virtual bool getCurrentScreenMode(Display::ScreenMode &sm)