A basic graphics package for the LPC4088 Display Module.

Dependents:   lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI lpc4088_displaymodule_fs_aid ... more

Fork of DMBasicGUI by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Sun Dec 21 13:53:07 2014 +0100
Revision:
5:f4de114c31c3
Child:
13:bff2288c2c61
- Added support for RAW images
- Added SlideShow + App for it
- Moved App-specific stuff out from the AppLauncher and into main

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 5:f4de114c31c3 1 #include "mbed.h"
embeddedartists 5:f4de114c31c3 2 #include "Renderer.h"
embeddedartists 5:f4de114c31c3 3 #include "DMBoard.h"
embeddedartists 5:f4de114c31c3 4
embeddedartists 5:f4de114c31c3 5 #if !defined(MIN)
embeddedartists 5:f4de114c31c3 6 #define MIN(__a, __b) (((__a)<(__b))?(__a):(__b))
embeddedartists 5:f4de114c31c3 7 #endif
embeddedartists 5:f4de114c31c3 8
embeddedartists 5:f4de114c31c3 9 Renderer::Renderer(/*LcdController::Config* screen, EaLcdBoard* lcdBoard*/)
embeddedartists 5:f4de114c31c3 10 {
embeddedartists 5:f4de114c31c3 11 memset(layers, 0, sizeof(layerinfo_t)*MaxNumLayers);
embeddedartists 5:f4de114c31c3 12 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 13 layers[i].used = false;
embeddedartists 5:f4de114c31c3 14 order[i] = NULL;
embeddedartists 5:f4de114c31c3 15 }
embeddedartists 5:f4de114c31c3 16
embeddedartists 5:f4de114c31c3 17 numRegisteredLayers = 0;
embeddedartists 5:f4de114c31c3 18 t = NULL;
embeddedartists 5:f4de114c31c3 19 activeBackBuffer = 0;
embeddedartists 5:f4de114c31c3 20 display = DMBoard::instance().display();
embeddedartists 5:f4de114c31c3 21
embeddedartists 5:f4de114c31c3 22 this->screenWidth = display->width();
embeddedartists 5:f4de114c31c3 23 this->screenHeight = display->height();
embeddedartists 5:f4de114c31c3 24 this->screenPixels = this->screenWidth * this->screenHeight;
embeddedartists 5:f4de114c31c3 25
embeddedartists 5:f4de114c31c3 26 // Assume screen->bpp == Bpp_16
embeddedartists 5:f4de114c31c3 27 this->screenBytes = display->bytesPerPixel() * this->screenPixels;
embeddedartists 5:f4de114c31c3 28
embeddedartists 5:f4de114c31c3 29 ImageBackBuffer[0] = (image_t)display->allocateFramebuffer();//malloc(this->screenBytes);
embeddedartists 5:f4de114c31c3 30 ImageBackBuffer[1] = (image_t)display->allocateFramebuffer();//malloc(this->screenBytes);
embeddedartists 5:f4de114c31c3 31 if ((ImageBackBuffer[0] == NULL) || (ImageBackBuffer[1] == NULL)) {
embeddedartists 5:f4de114c31c3 32 printf("Failed to allocate buffer(s) for Renderer. Halting...\n");
embeddedartists 5:f4de114c31c3 33 while(1) {
embeddedartists 5:f4de114c31c3 34 ;
embeddedartists 5:f4de114c31c3 35 }
embeddedartists 5:f4de114c31c3 36 }
embeddedartists 5:f4de114c31c3 37 memset(ImageBackBuffer[0], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 38 memset(ImageBackBuffer[1], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 39 }
embeddedartists 5:f4de114c31c3 40
embeddedartists 5:f4de114c31c3 41 Renderer::~Renderer()
embeddedartists 5:f4de114c31c3 42 {
embeddedartists 5:f4de114c31c3 43 free(ImageBackBuffer[0]);
embeddedartists 5:f4de114c31c3 44 free(ImageBackBuffer[1]);
embeddedartists 5:f4de114c31c3 45 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 46 if (layers[i].used) {
embeddedartists 5:f4de114c31c3 47 free(layers[i].tmp);
embeddedartists 5:f4de114c31c3 48 delete(layers[i].lock);
embeddedartists 5:f4de114c31c3 49 }
embeddedartists 5:f4de114c31c3 50 }
embeddedartists 5:f4de114c31c3 51 }
embeddedartists 5:f4de114c31c3 52
embeddedartists 5:f4de114c31c3 53 uint32_t Renderer::registerUser(int layer, int xoff, int yoff, int width, int height)
embeddedartists 5:f4de114c31c3 54 {
embeddedartists 5:f4de114c31c3 55 setupMutex.lock();
embeddedartists 5:f4de114c31c3 56 if (numRegisteredLayers < MaxNumLayers) {
embeddedartists 5:f4de114c31c3 57 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 58 if (!layers[i].used) {
embeddedartists 5:f4de114c31c3 59 // found a spot
embeddedartists 5:f4de114c31c3 60 layers[i].used = true;
embeddedartists 5:f4de114c31c3 61 layers[i].x0 = xoff;
embeddedartists 5:f4de114c31c3 62 layers[i].y0 = yoff;
embeddedartists 5:f4de114c31c3 63 layers[i].x1 = MIN(xoff+width, screenWidth);
embeddedartists 5:f4de114c31c3 64 layers[i].y1 = MIN(yoff+height, screenHeight);
embeddedartists 5:f4de114c31c3 65 layers[i].width = width;
embeddedartists 5:f4de114c31c3 66 layers[i].clippedHeight = layers[i].y1 - layers[i].y0;
embeddedartists 5:f4de114c31c3 67 layers[i].zorder = layer;
embeddedartists 5:f4de114c31c3 68 layers[i].signalId = 1;//(1<<i);
embeddedartists 5:f4de114c31c3 69 layers[i].lock = new Mutex();
embeddedartists 5:f4de114c31c3 70 layers[i].newData = NULL;
embeddedartists 5:f4de114c31c3 71 layers[i].activeData = NULL;
embeddedartists 5:f4de114c31c3 72 layers[i].fullscreen = false;
embeddedartists 5:f4de114c31c3 73 if ((xoff == 0) && (yoff == 0) && (width == screenWidth) && (height == screenHeight)) {
embeddedartists 5:f4de114c31c3 74 layers[i].fullscreen = true;
embeddedartists 5:f4de114c31c3 75 }
embeddedartists 5:f4de114c31c3 76
embeddedartists 5:f4de114c31c3 77 layers[i].tmp = (uint16_t*)malloc(width*layers[i].clippedHeight*2);
embeddedartists 5:f4de114c31c3 78 if (layers[i].tmp != NULL) {
embeddedartists 5:f4de114c31c3 79 memset(layers[i].tmp, 0, width*layers[i].clippedHeight*2);
embeddedartists 5:f4de114c31c3 80 }
embeddedartists 5:f4de114c31c3 81
embeddedartists 5:f4de114c31c3 82
embeddedartists 5:f4de114c31c3 83 // sort the order
embeddedartists 5:f4de114c31c3 84 for (int j = 0; j < MaxNumLayers; j++) {
embeddedartists 5:f4de114c31c3 85 if (order[j] == NULL) {
embeddedartists 5:f4de114c31c3 86 // no more layers so add the new one to the top
embeddedartists 5:f4de114c31c3 87 order[j] = &(layers[i]);
embeddedartists 5:f4de114c31c3 88 break;
embeddedartists 5:f4de114c31c3 89 }
embeddedartists 5:f4de114c31c3 90 if (order[j]->zorder > layer) {
embeddedartists 5:f4de114c31c3 91 // should insert the new layer here
embeddedartists 5:f4de114c31c3 92 for (int k = numRegisteredLayers; k > j; k--) {
embeddedartists 5:f4de114c31c3 93 order[k] = order[k-1];
embeddedartists 5:f4de114c31c3 94 }
embeddedartists 5:f4de114c31c3 95 order[j] = &(layers[i]);
embeddedartists 5:f4de114c31c3 96 break;
embeddedartists 5:f4de114c31c3 97 }
embeddedartists 5:f4de114c31c3 98 }
embeddedartists 5:f4de114c31c3 99
embeddedartists 5:f4de114c31c3 100 // Cause a repaint of all layers. It does not have to be immediate
embeddedartists 5:f4de114c31c3 101 // as for unregisterUser() - it is enough that it is done next time.
embeddedartists 5:f4de114c31c3 102 order[0]->activeData = NULL;
embeddedartists 5:f4de114c31c3 103
embeddedartists 5:f4de114c31c3 104 numRegisteredLayers++;
embeddedartists 5:f4de114c31c3 105
embeddedartists 5:f4de114c31c3 106 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 107 return (uint32_t)(&(layers[i]));
embeddedartists 5:f4de114c31c3 108 }
embeddedartists 5:f4de114c31c3 109 }
embeddedartists 5:f4de114c31c3 110 }
embeddedartists 5:f4de114c31c3 111 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 112 return 0;
embeddedartists 5:f4de114c31c3 113 }
embeddedartists 5:f4de114c31c3 114
embeddedartists 5:f4de114c31c3 115 uint32_t Renderer::registerFullscreenUser(int layer)
embeddedartists 5:f4de114c31c3 116 {
embeddedartists 5:f4de114c31c3 117 return registerUser(layer, 0, 0, screenWidth, screenHeight);
embeddedartists 5:f4de114c31c3 118 }
embeddedartists 5:f4de114c31c3 119
embeddedartists 5:f4de114c31c3 120 void Renderer::unregisterUser(uint32_t handle)
embeddedartists 5:f4de114c31c3 121 {
embeddedartists 5:f4de114c31c3 122 setupMutex.lock();
embeddedartists 5:f4de114c31c3 123 if (handle != 0) {
embeddedartists 5:f4de114c31c3 124 layerinfo_t* layer = (layerinfo_t*)handle;
embeddedartists 5:f4de114c31c3 125 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 126 if (order[i] == layer) {
embeddedartists 5:f4de114c31c3 127 layer->used = false;
embeddedartists 5:f4de114c31c3 128 free(layer->tmp);
embeddedartists 5:f4de114c31c3 129 delete layer->lock;
embeddedartists 5:f4de114c31c3 130
embeddedartists 5:f4de114c31c3 131 // move all layers "down" one step
embeddedartists 5:f4de114c31c3 132 for (int j = i+1; j<numRegisteredLayers; j++) {
embeddedartists 5:f4de114c31c3 133 order[j-1] = order[j];
embeddedartists 5:f4de114c31c3 134 }
embeddedartists 5:f4de114c31c3 135 order[numRegisteredLayers-1] = NULL;
embeddedartists 5:f4de114c31c3 136 numRegisteredLayers--;
embeddedartists 5:f4de114c31c3 137
embeddedartists 5:f4de114c31c3 138 // cause a repaint
embeddedartists 5:f4de114c31c3 139 if (order[0] != NULL) {
embeddedartists 5:f4de114c31c3 140 order[0]->activeData = NULL;
embeddedartists 5:f4de114c31c3 141
embeddedartists 5:f4de114c31c3 142 // Very important that the signal is not sent while the lock is held
embeddedartists 5:f4de114c31c3 143 // as it will cause the renderer thread be able to take it also
embeddedartists 5:f4de114c31c3 144 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 145 t->signal_set(layer->signalId);
embeddedartists 5:f4de114c31c3 146 return;
embeddedartists 5:f4de114c31c3 147 } else {
embeddedartists 5:f4de114c31c3 148 // no longer anything to show, clear back buffers
embeddedartists 5:f4de114c31c3 149 memset(ImageBackBuffer[0], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 150 memset(ImageBackBuffer[1], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 151 }
embeddedartists 5:f4de114c31c3 152
embeddedartists 5:f4de114c31c3 153 break;
embeddedartists 5:f4de114c31c3 154 }
embeddedartists 5:f4de114c31c3 155 }
embeddedartists 5:f4de114c31c3 156 }
embeddedartists 5:f4de114c31c3 157 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 158 }
embeddedartists 5:f4de114c31c3 159
embeddedartists 5:f4de114c31c3 160 void Renderer::setFramebuffer(uint32_t handle, const uint16_t* data)
embeddedartists 5:f4de114c31c3 161 {
embeddedartists 5:f4de114c31c3 162 layerinfo_t* layer = (layerinfo_t*)handle;
embeddedartists 5:f4de114c31c3 163
embeddedartists 5:f4de114c31c3 164 // make sure that the render thread is not using the data when
embeddedartists 5:f4de114c31c3 165 // we change it
embeddedartists 5:f4de114c31c3 166 layer->lock->lock();
embeddedartists 5:f4de114c31c3 167 layer->newData = data;
embeddedartists 5:f4de114c31c3 168 layer->activeData = NULL;
embeddedartists 5:f4de114c31c3 169 layer->lock->unlock();
embeddedartists 5:f4de114c31c3 170
embeddedartists 5:f4de114c31c3 171 // notify the renderer that there is new data for our layer
embeddedartists 5:f4de114c31c3 172 t->signal_set(layer->signalId);
embeddedartists 5:f4de114c31c3 173 }
embeddedartists 5:f4de114c31c3 174
embeddedartists 5:f4de114c31c3 175 void Renderer::render()
embeddedartists 5:f4de114c31c3 176 {
embeddedartists 5:f4de114c31c3 177 int mask = 1;//(1<<MaxNumLayers) - 1;
embeddedartists 5:f4de114c31c3 178 while(true)
embeddedartists 5:f4de114c31c3 179 {
embeddedartists 5:f4de114c31c3 180 osEvent ev = Thread::signal_wait(mask);
embeddedartists 5:f4de114c31c3 181 if (ev.status == osEventSignal) {
embeddedartists 5:f4de114c31c3 182 setupMutex.lock();
embeddedartists 5:f4de114c31c3 183 for (int i = 0; i < numRegisteredLayers; i++) {
embeddedartists 5:f4de114c31c3 184 if (order[i]->activeData != order[i]->newData) {
embeddedartists 5:f4de114c31c3 185 //if (order[i]->signalId & ev.value.signals) {
embeddedartists 5:f4de114c31c3 186
embeddedartists 5:f4de114c31c3 187 int n = (activeBackBuffer + 1) & 1;
embeddedartists 5:f4de114c31c3 188
embeddedartists 5:f4de114c31c3 189 // if (i == 0) {
embeddedartists 5:f4de114c31c3 190 // // TEMPORARY
embeddedartists 5:f4de114c31c3 191 // board->setFrameBuffer((uint32_t)ImageBackBuffer[n]);
embeddedartists 5:f4de114c31c3 192 // if (order[i]->activeData != NULL && order[i]->newData != NULL) {
embeddedartists 5:f4de114c31c3 193 // for (int y = 0; y < order[i]->clippedHeight; y++) {
embeddedartists 5:f4de114c31c3 194 // for (int x = 0; x < order[i]->width; x++) {
embeddedartists 5:f4de114c31c3 195 // if (order[i]->activeData[y*order[i]->width+x] != order[i]->newData[y*order[i]->width+x]) {
embeddedartists 5:f4de114c31c3 196 // printf("Difference in x,y {%d,%d} active is 0x%04x, new is 0x%04x\n", x, y,
embeddedartists 5:f4de114c31c3 197 // order[i]->activeData[y*order[i]->width+x], order[i]->newData[y*order[i]->width+x]);
embeddedartists 5:f4de114c31c3 198 // }
embeddedartists 5:f4de114c31c3 199 // }
embeddedartists 5:f4de114c31c3 200 // }
embeddedartists 5:f4de114c31c3 201 // }
embeddedartists 5:f4de114c31c3 202 // }
embeddedartists 5:f4de114c31c3 203
embeddedartists 5:f4de114c31c3 204 // Layer i have new data
embeddedartists 5:f4de114c31c3 205 // redraw this layer and all on top of it
embeddedartists 5:f4de114c31c3 206 for (int j = i; j < numRegisteredLayers; j++) {
embeddedartists 5:f4de114c31c3 207 layerinfo_t* layer = order[j];
embeddedartists 5:f4de114c31c3 208 layer->lock->lock();
embeddedartists 5:f4de114c31c3 209 layer->activeData = layer->newData;
embeddedartists 5:f4de114c31c3 210 memcpy(layer->tmp, layer->newData, layer->width*layer->clippedHeight*2);
embeddedartists 5:f4de114c31c3 211 layer->lock->unlock();
embeddedartists 5:f4de114c31c3 212 if (layer->activeData != NULL) {
embeddedartists 5:f4de114c31c3 213 if (layer->fullscreen) {
embeddedartists 5:f4de114c31c3 214 memcpy(ImageBackBuffer[n], layer->tmp, screenBytes);
embeddedartists 5:f4de114c31c3 215 } else {
embeddedartists 5:f4de114c31c3 216 for (int y = 0; y < layer->clippedHeight; y++) {
embeddedartists 5:f4de114c31c3 217 memcpy(ImageBackBuffer[n] + ((y + layer->y0) * screenWidth) + layer->x0,
embeddedartists 5:f4de114c31c3 218 layer->tmp + (y * layer->width),
embeddedartists 5:f4de114c31c3 219 (layer->x1 - layer->x0) * 2);
embeddedartists 5:f4de114c31c3 220 }
embeddedartists 5:f4de114c31c3 221 }
embeddedartists 5:f4de114c31c3 222 }
embeddedartists 5:f4de114c31c3 223 }
embeddedartists 5:f4de114c31c3 224
embeddedartists 5:f4de114c31c3 225 //board->setFrameBuffer((uint32_t)ImageBackBuffer[n]);
embeddedartists 5:f4de114c31c3 226 display->setFramebuffer(ImageBackBuffer[n]);
embeddedartists 5:f4de114c31c3 227 if (i == (numRegisteredLayers - 1)) {
embeddedartists 5:f4de114c31c3 228 // only top layer changed, no need to copy entire back buffer
embeddedartists 5:f4de114c31c3 229 } else {
embeddedartists 5:f4de114c31c3 230 // more layers exist on top so the back buffer must be updated
embeddedartists 5:f4de114c31c3 231 memcpy(ImageBackBuffer[activeBackBuffer], ImageBackBuffer[n], screenBytes);
embeddedartists 5:f4de114c31c3 232 }
embeddedartists 5:f4de114c31c3 233 activeBackBuffer = n;
embeddedartists 5:f4de114c31c3 234 break;
embeddedartists 5:f4de114c31c3 235 }
embeddedartists 5:f4de114c31c3 236 }
embeddedartists 5:f4de114c31c3 237 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 238 }
embeddedartists 5:f4de114c31c3 239 }
embeddedartists 5:f4de114c31c3 240 }