diff options
Diffstat (limited to 'src/dev')
-rw-r--r-- | src/dev/arm/hdlcd.cc | 124 | ||||
-rw-r--r-- | src/dev/arm/hdlcd.hh | 18 | ||||
-rw-r--r-- | src/dev/arm/pl111.cc | 103 | ||||
-rw-r--r-- | src/dev/arm/pl111.hh | 13 |
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 §ion) 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 §ion) 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 §ion) 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(); |