summaryrefslogtreecommitdiff
path: root/src/dev
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev')
-rw-r--r--src/dev/arm/hdlcd.cc124
-rw-r--r--src/dev/arm/hdlcd.hh18
-rw-r--r--src/dev/arm/pl111.cc103
-rw-r--r--src/dev/arm/pl111.hh13
4 files changed, 130 insertions, 128 deletions
diff --git a/src/dev/arm/hdlcd.cc b/src/dev/arm/hdlcd.cc
index 37569b22b..b1c1c450b 100644
--- a/src/dev/arm/hdlcd.cc
+++ b/src/dev/arm/hdlcd.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2013 ARM Limited
+ * Copyright (c) 2010-2013, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -37,15 +37,15 @@
* Authors: Chris Emmons
*/
+#include "dev/arm/hdlcd.hh"
+
#include "base/vnc/vncinput.hh"
-#include "base/bitmap.hh"
#include "base/output.hh"
#include "base/trace.hh"
#include "debug/HDLcd.hh"
#include "debug/Uart.hh"
#include "dev/arm/amba_device.hh"
#include "dev/arm/base_gic.hh"
-#include "dev/arm/hdlcd.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"
#include "sim/system.hh"
@@ -63,10 +63,11 @@ HDLcd::HDLcd(const Params *p)
h_sync(0), h_back_porch(0), h_data(0), h_front_porch(0),
polarities(0), command(0), pixel_format(0),
red_select(0), green_select(0), blue_select(0),
- pixelClock(p->pixel_clock), vnc(p->vnc), bmp(NULL), pic(NULL),
+ pixelClock(p->pixel_clock),
+ fb(0, 0), vnc(p->vnc), bmp(&fb), pic(NULL),
frameReadStartTime(0),
dmaStartAddr(0), dmaCurAddr(0), dmaMaxAddr(0), dmaPendingNum(0),
- frameUnderrun(false), virtualDisplayBuffer(NULL), pixelBufferSize(0),
+ frameUnderrun(false), pixelBufferSize(0),
pixelIndex(0), doUpdateParams(false), frameUnderway(false),
dmaBytesInFlight(0),
startFrameEvent(this), endFrameEvent(this), renderPixelEvent(this),
@@ -81,13 +82,11 @@ HDLcd::HDLcd(const Params *p)
dmaDoneEventFree[i] = &dmaDoneEventAll[i];
if (vnc)
- vnc->setFramebufferAddr(NULL);
+ vnc->setFrameBuffer(&fb);
}
HDLcd::~HDLcd()
{
- if (virtualDisplayBuffer)
- delete [] virtualDisplayBuffer;
}
// read registers and frame buffer
@@ -315,8 +314,14 @@ HDLcd::write(PacketPtr pkt)
void
HDLcd::updateVideoParams(bool unserializing = false)
{
- const uint16_t bpp = bytesPerPixel() << 3;
- const size_t buffer_size = bytesPerPixel() * width() * height();
+ const uint16_t bpp M5_VAR_USED = bytesPerPixel() << 3;
+
+ // Workaround configuration bugs where multiple display
+ // controllers are attached to the same VNC server by reattaching
+ // enabled devices. This isn't ideal, but works as long as only
+ // one display controller is active at a time.
+ if (command.enable && vnc)
+ vnc->setFrameBuffer(&fb);
// updating these parameters while LCD is enabled is not supported
if (frameUnderway && !unserializing)
@@ -328,18 +333,14 @@ HDLcd::updateVideoParams(bool unserializing = false)
// there must be no outstanding DMA transactions for this to work
if (!unserializing) {
assert(dmaPendingNum == 0);
- if (virtualDisplayBuffer)
- delete [] virtualDisplayBuffer;
- virtualDisplayBuffer = new uint8_t[buffer_size];
- memset(virtualDisplayBuffer, 0, buffer_size);
- }
- assert(virtualDisplayBuffer);
- if (vnc)
- vnc->setFramebufferAddr(virtualDisplayBuffer);
+ virtualDisplayBuffer.resize(bytesPerPixel() * area());
+ fb.resize(width(), height());
+ fb.clear();
- if (bmp)
- delete bmp;
+ std::fill(virtualDisplayBuffer.begin(), virtualDisplayBuffer.end(),
+ 0);
+ }
DPRINTF(HDLcd, "bpp = %d\n", bpp);
DPRINTF(HDLcd, "display size = %d x %d\n", width(), height());
@@ -354,61 +355,11 @@ HDLcd::updateVideoParams(bool unserializing = false)
DPRINTF(HDLcd, "simulated refresh rate ~ %.1ffps generating ~ %.1fMB/s "
"traffic ([%.1fMHz, T=%d sim clocks] pclk, %d bpp => %.1fMB/s peak requirement)\n",
fps,
- fps * buffer_size / 1024 / 1024,
+ fps * virtualDisplayBuffer.size() / 1024 / 1024,
(double)SimClock::Frequency / pixelClock / 1000000.0,
pixelClock,
bpp,
(double)(SimClock::Frequency / pixelClock * (bpp / 8)) / 1024 / 1024);
-
- if (pixel_format.big_endian)
- panic("Big Endian pixel format not implemented by HDLcd controller");
-
- if (vnc) {
- if ((bpp == 24) &&
- (red_select.size == 8) &&
- (blue_select.size == 8) &&
- (green_select.size == 8) &&
- (green_select.offset == 8)) {
- if ((blue_select.offset == 0) &&
- (red_select.offset == 16)) {
- vnc->setFrameBufferParams(VideoConvert::rgb8888, width(),
- height());
- bmp = new Bitmap(VideoConvert::rgb8888, width(), height(),
- virtualDisplayBuffer);
- DPRINTF(HDLcd, "color mode: rgb888\n");
- } else if ((red_select.offset == 0) &&
- (blue_select.offset == 16)) {
- vnc->setFrameBufferParams(VideoConvert::bgr8888, width(),
- height());
- bmp = new Bitmap(VideoConvert::bgr8888, width(), height(),
- virtualDisplayBuffer);
- DPRINTF(HDLcd, "color mode: bgr888\n");
- }
- } else if ((bpp == 16) &&
- (red_select.size == 5) &&
- (blue_select.size == 5) &&
- (green_select.size == 6) &&
- (green_select.offset == 5)) {
- if ((blue_select.offset == 0) &&
- (red_select.offset == 11)) {
- vnc->setFrameBufferParams(VideoConvert::rgb565, width(),
- height());
- bmp = new Bitmap(VideoConvert::rgb565, width(), height(),
- virtualDisplayBuffer);
- DPRINTF(HDLcd, "color mode: rgb565\n");
- } else if ((red_select.offset == 0) &&
- (blue_select.offset == 11)) {
- vnc->setFrameBufferParams(VideoConvert::bgr565, width(),
- height());
- bmp = new Bitmap(VideoConvert::bgr565, width(), height(),
- virtualDisplayBuffer);
- DPRINTF(HDLcd, "color mode: bgr565\n");
- }
- } else {
- DPRINTF(HDLcd, "color mode: undefined\n");
- panic("Unimplemented video mode\n");
- }
- }
}
void
@@ -424,7 +375,7 @@ HDLcd::startFrame()
doUpdateParams = false;
}
frameUnderway = true;
- assert(virtualDisplayBuffer);
+ assert(!virtualDisplayBuffer.empty());
assert(pixelBufferSize == 0);
assert(dmaBytesInFlight == 0);
assert(dmaPendingNum == 0);
@@ -484,10 +435,11 @@ HDLcd::fillPixelBuffer()
// will be uncacheable as well. If we have uncacheable and cacheable
// requests in the memory system for the same address it won't be
// pleased
+ uint8_t *const dma_dst(
+ virtualDisplayBuffer.data() + dmaCurAddr - dmaStartAddr);
event->setTransactionSize(transaction_size);
dmaPort.dmaAction(MemCmd::ReadReq, dmaCurAddr, transaction_size, event,
- virtualDisplayBuffer + dmaCurAddr - dmaStartAddr,
- 0, Request::UNCACHEABLE);
+ dma_dst, 0, Request::UNCACHEABLE);
dmaCurAddr += transaction_size;
dmaBytesInFlight += transaction_size;
}
@@ -549,6 +501,16 @@ HDLcd::renderPixel()
schedule(renderPixelEvent, nextEventTick);
}
+PixelConverter
+HDLcd::pixelConverter() const
+{
+ return PixelConverter(
+ bytesPerPixel(),
+ red_select.offset, green_select.offset, blue_select.offset,
+ red_select.size, green_select.size, blue_select.size,
+ pixel_format.big_endian ? BigEndianByteOrder : LittleEndianByteOrder);
+}
+
void
HDLcd::endFrame() {
assert(pixelBufferSize == 0);
@@ -556,6 +518,8 @@ HDLcd::endFrame() {
assert(dmaBytesInFlight == 0);
assert(dmaDoneEventFree.size() == dmaDoneEventAll.size());
+ fb.copyIn(virtualDisplayBuffer, pixelConverter());
+
if (vnc)
vnc->setDirty();
@@ -563,10 +527,9 @@ HDLcd::endFrame() {
if (!pic)
pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
- assert(bmp);
assert(pic);
pic->seekp(0);
- bmp->write(pic);
+ bmp.write(*pic);
}
// start the next frame
@@ -664,8 +627,7 @@ HDLcd::serialize(std::ostream &os)
SERIALIZE_SCALAR(dmaPendingNum);
SERIALIZE_SCALAR(frameUnderrun);
- const size_t buffer_size = bytesPerPixel() * width() * height();
- SERIALIZE_ARRAY(virtualDisplayBuffer, buffer_size);
+ arrayParamOut(os, "virtualDisplayBuffer", virtualDisplayBuffer);
SERIALIZE_SCALAR(pixelBufferSize);
SERIALIZE_SCALAR(pixelIndex);
@@ -777,9 +739,7 @@ HDLcd::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(frameUnderrun);
UNSERIALIZE_SCALAR(dmaBytesInFlight);
- const size_t buffer_size = bytesPerPixel() * width() * height();
- virtualDisplayBuffer = new uint8_t[buffer_size];
- UNSERIALIZE_ARRAY(virtualDisplayBuffer, buffer_size);
+ arrayParamIn(cp, section, "virtualDisplayBuffer", virtualDisplayBuffer);
UNSERIALIZE_SCALAR(pixelBufferSize);
UNSERIALIZE_SCALAR(pixelIndex);
@@ -823,6 +783,8 @@ HDLcd::unserialize(Checkpoint *cp, const std::string &section)
if (frameUnderway) {
updateVideoParams(true);
+ fb.resize(width(), height());
+ fb.copyIn(virtualDisplayBuffer, pixelConverter());
if (vnc)
vnc->setDirty();
}
diff --git a/src/dev/arm/hdlcd.hh b/src/dev/arm/hdlcd.hh
index ba22cc163..61d2dc5d7 100644
--- a/src/dev/arm/hdlcd.hh
+++ b/src/dev/arm/hdlcd.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2013 ARM Limited
+ * Copyright (c) 2010-2013, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -83,13 +83,15 @@
#define __DEV_ARM_HDLCD_HH__
#include <fstream>
+#include <memory>
+#include "base/bitmap.hh"
+#include "base/framebuffer.hh"
#include "dev/arm/amba_device.hh"
#include "params/HDLcd.hh"
#include "sim/serialize.hh"
class VncInput;
-class Bitmap;
class HDLcd: public AmbaDmaDevice
{
@@ -142,6 +144,8 @@ class HDLcd: public AmbaDmaDevice
/** AXI port width in bytes */
static const size_t AXI_PORT_WIDTH = 8;
+ static const size_t MAX_BURST_SIZE = MAX_BURST_LEN * AXI_PORT_WIDTH;
+
/**
* @name RegisterFieldLayouts
* Bit layout declarations for multi-field registers.
@@ -242,11 +246,13 @@ class HDLcd: public AmbaDmaDevice
/** Pixel clock period */
const Tick pixelClock;
+ FrameBuffer fb;
+
/** VNC server */
VncInput *vnc;
/** Helper to write out bitmaps */
- Bitmap *bmp;
+ Bitmap bmp;
/** Picture of what the current frame buffer looks like */
std::ostream *pic;
@@ -325,7 +331,7 @@ class HDLcd: public AmbaDmaDevice
bool frameUnderrun;
/** HDLcd virtual display buffer */
- uint8_t *virtualDisplayBuffer;
+ std::vector<uint8_t> virtualDisplayBuffer;
/** Size of the pixel buffer */
size_t pixelBufferSize;
@@ -402,6 +408,8 @@ class HDLcd: public AmbaDmaDevice
return fb_line_count.fb_line_count;
}
+ inline size_t area() const { return height() * width(); }
+
/**
* Gets the total number of pixel clocks per display line.
*
@@ -436,6 +444,8 @@ class HDLcd: public AmbaDmaDevice
/** Called when it is time to render a pixel */
void renderPixel();
+ PixelConverter pixelConverter() const;
+
/** Start of frame event */
EventWrapper<HDLcd, &HDLcd::startFrame> startFrameEvent;
diff --git a/src/dev/arm/pl111.cc b/src/dev/arm/pl111.cc
index a5b9b412c..fcce09f50 100644
--- a/src/dev/arm/pl111.cc
+++ b/src/dev/arm/pl111.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2012 ARM Limited
+ * Copyright (c) 2010-2012, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -39,7 +39,6 @@
*/
#include "base/vnc/vncinput.hh"
-#include "base/bitmap.hh"
#include "base/output.hh"
#include "base/trace.hh"
#include "debug/PL111.hh"
@@ -63,7 +62,9 @@ Pl111::Pl111(const Params *p)
clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0),
- pixelClock(p->pixel_clock), vnc(p->vnc), bmp(NULL), pic(NULL),
+ pixelClock(p->pixel_clock),
+ converter(PixelConverter::rgba8888_le), fb(LcdMaxWidth, LcdMaxHeight),
+ vnc(p->vnc), bmp(&fb), pic(NULL),
width(LcdMaxWidth), height(LcdMaxHeight),
bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
@@ -83,7 +84,7 @@ Pl111::Pl111(const Params *p)
dmaDoneEventFree[i] = &dmaDoneEventAll[i];
if (vnc)
- vnc->setFramebufferAddr(dmaBuffer);
+ vnc->setFrameBuffer(&fb);
}
Pl111::~Pl111()
@@ -378,45 +379,66 @@ Pl111::write(PacketPtr pkt)
return pioDelay;
}
+PixelConverter
+Pl111::pixelConverter() const
+{
+ unsigned rw, gw, bw;
+ unsigned offsets[3];
+
+ switch (lcdControl.lcdbpp) {
+ case bpp24:
+ rw = gw = bw = 8;
+ offsets[0] = 0;
+ offsets[1] = 8;
+ offsets[2] = 16;
+ break;
+
+ case bpp16m565:
+ rw = 5;
+ gw = 6;
+ bw = 5;
+ offsets[0] = 0;
+ offsets[1] = 5;
+ offsets[2] = 11;
+ break;
+
+ default:
+ panic("Unimplemented video mode\n");
+ }
+
+ if (lcdControl.bgr) {
+ return PixelConverter(
+ bytesPerPixel,
+ offsets[2], offsets[1], offsets[0],
+ rw, gw, bw,
+ LittleEndianByteOrder);
+ } else {
+ return PixelConverter(
+ bytesPerPixel,
+ offsets[0], offsets[1], offsets[2],
+ rw, gw, bw,
+ LittleEndianByteOrder);
+ }
+}
+
void
Pl111::updateVideoParams()
{
- if (lcdControl.lcdbpp == bpp24) {
- bytesPerPixel = 4;
- } else if (lcdControl.lcdbpp == bpp16m565) {
- bytesPerPixel = 2;
- }
+ if (lcdControl.lcdbpp == bpp24) {
+ bytesPerPixel = 4;
+ } else if (lcdControl.lcdbpp == bpp16m565) {
+ bytesPerPixel = 2;
+ }
- if (vnc) {
- if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
- vnc->setFrameBufferParams(VideoConvert::bgr8888, width,
- height);
- else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
- vnc->setFrameBufferParams(VideoConvert::rgb8888, width,
- height);
- else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
- vnc->setFrameBufferParams(VideoConvert::bgr565, width,
- height);
- else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
- vnc->setFrameBufferParams(VideoConvert::rgb565, width,
- height);
- else
- panic("Unimplemented video mode\n");
- }
+ fb.resize(width, height);
+ converter = pixelConverter();
- if (bmp)
- delete bmp;
-
- if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
- bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
- else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
- bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
- else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
- bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
- else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
- bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
- else
- panic("Unimplemented video mode\n");
+ // Workaround configuration bugs where multiple display
+ // controllers are attached to the same VNC server by reattaching
+ // enabled devices. This isn't ideal, but works as long as only
+ // one display controller is active at a time.
+ if (lcdControl.lcdpwr && vnc)
+ vnc->setFrameBuffer(&fb);
}
void
@@ -493,6 +515,7 @@ Pl111::dmaDone()
}
assert(!readEvent.scheduled());
+ fb.copyIn(dmaBuffer, converter);
if (vnc)
vnc->setDirty();
@@ -502,10 +525,9 @@ Pl111::dmaDone()
if (!pic)
pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
- assert(bmp);
assert(pic);
pic->seekp(0);
- bmp->write(pic);
+ bmp.write(*pic);
}
// schedule the next read based on when the last frame started
@@ -721,6 +743,7 @@ Pl111::unserialize(Checkpoint *cp, const std::string &section)
if (lcdControl.lcdpwr) {
updateVideoParams();
+ fb.copyIn(dmaBuffer, converter);
if (vnc)
vnc->setDirty();
}
diff --git a/src/dev/arm/pl111.hh b/src/dev/arm/pl111.hh
index a7c158473..85973bbc7 100644
--- a/src/dev/arm/pl111.hh
+++ b/src/dev/arm/pl111.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2012 ARM Limited
+ * Copyright (c) 2010-2012, 2015 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -47,13 +47,15 @@
#define __DEV_ARM_PL111_HH__
#include <fstream>
+#include <memory>
+#include "base/bitmap.hh"
+#include "base/framebuffer.hh"
#include "dev/arm/amba_device.hh"
#include "params/Pl111.hh"
#include "sim/serialize.hh"
class VncInput;
-class Bitmap;
class Pl111: public AmbaDmaDevice
{
@@ -256,11 +258,14 @@ class Pl111: public AmbaDmaDevice
/** Pixel clock */
Tick pixelClock;
+ PixelConverter converter;
+ FrameBuffer fb;
+
/** VNC server */
VncInput *vnc;
/** Helper to write out bitmaps */
- Bitmap *bmp;
+ Bitmap bmp;
/** Picture of what the current frame buffer looks like */
std::ostream *pic;
@@ -295,6 +300,8 @@ class Pl111: public AmbaDmaDevice
/** Number of pending dma reads */
uint32_t dmaPendingNum;
+ PixelConverter pixelConverter() const;
+
/** Send updated parameters to the vnc server */
void updateVideoParams();