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:
Mon Mar 09 10:40:55 2015 +0100
Revision:
13:bff2288c2c61
Parent:
5:f4de114c31c3
Child:
15:a68bb30ab95e
Added documentation of the SlideShow related classes

Who changed what in which revision?

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