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 Nov 04 14:31:50 2019 +0000
Revision:
22:f0d00f29bfeb
Parent:
21:0038059e3a8f
More updates related to mbed OS 5

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 activeBackBuffer = 0;
embeddedartists 5:f4de114c31c3 43 display = DMBoard::instance().display();
embeddedartists 5:f4de114c31c3 44
embeddedartists 5:f4de114c31c3 45 this->screenWidth = display->width();
embeddedartists 5:f4de114c31c3 46 this->screenHeight = display->height();
embeddedartists 5:f4de114c31c3 47 this->screenPixels = this->screenWidth * this->screenHeight;
embeddedartists 5:f4de114c31c3 48
embeddedartists 5:f4de114c31c3 49 // Assume screen->bpp == Bpp_16
embeddedartists 5:f4de114c31c3 50 this->screenBytes = display->bytesPerPixel() * this->screenPixels;
embeddedartists 5:f4de114c31c3 51
embeddedartists 13:bff2288c2c61 52 ImageBackBuffer[0] = (image_t)display->allocateFramebuffer();
embeddedartists 13:bff2288c2c61 53 ImageBackBuffer[1] = (image_t)display->allocateFramebuffer();
embeddedartists 5:f4de114c31c3 54 if ((ImageBackBuffer[0] == NULL) || (ImageBackBuffer[1] == NULL)) {
embeddedartists 5:f4de114c31c3 55 printf("Failed to allocate buffer(s) for Renderer. Halting...\n");
embeddedartists 5:f4de114c31c3 56 while(1) {
embeddedartists 5:f4de114c31c3 57 ;
embeddedartists 5:f4de114c31c3 58 }
embeddedartists 5:f4de114c31c3 59 }
embeddedartists 5:f4de114c31c3 60 memset(ImageBackBuffer[0], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 61 memset(ImageBackBuffer[1], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 62 }
embeddedartists 5:f4de114c31c3 63
embeddedartists 5:f4de114c31c3 64 Renderer::~Renderer()
embeddedartists 5:f4de114c31c3 65 {
embeddedartists 5:f4de114c31c3 66 free(ImageBackBuffer[0]);
embeddedartists 5:f4de114c31c3 67 free(ImageBackBuffer[1]);
embeddedartists 5:f4de114c31c3 68 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 69 if (layers[i].used) {
embeddedartists 5:f4de114c31c3 70 free(layers[i].tmp);
embeddedartists 5:f4de114c31c3 71 delete(layers[i].lock);
embeddedartists 5:f4de114c31c3 72 }
embeddedartists 5:f4de114c31c3 73 }
embeddedartists 5:f4de114c31c3 74 }
embeddedartists 5:f4de114c31c3 75
embeddedartists 5:f4de114c31c3 76 uint32_t Renderer::registerUser(int layer, int xoff, int yoff, int width, int height)
embeddedartists 5:f4de114c31c3 77 {
embeddedartists 5:f4de114c31c3 78 setupMutex.lock();
embeddedartists 5:f4de114c31c3 79 if (numRegisteredLayers < MaxNumLayers) {
embeddedartists 5:f4de114c31c3 80 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 81 if (!layers[i].used) {
embeddedartists 5:f4de114c31c3 82 // found a spot
embeddedartists 5:f4de114c31c3 83 layers[i].used = true;
embeddedartists 5:f4de114c31c3 84 layers[i].x0 = xoff;
embeddedartists 5:f4de114c31c3 85 layers[i].y0 = yoff;
embeddedartists 5:f4de114c31c3 86 layers[i].x1 = MIN(xoff+width, screenWidth);
embeddedartists 5:f4de114c31c3 87 layers[i].y1 = MIN(yoff+height, screenHeight);
embeddedartists 5:f4de114c31c3 88 layers[i].width = width;
embeddedartists 5:f4de114c31c3 89 layers[i].clippedHeight = layers[i].y1 - layers[i].y0;
embeddedartists 5:f4de114c31c3 90 layers[i].zorder = layer;
embeddedartists 5:f4de114c31c3 91 layers[i].signalId = 1;//(1<<i);
embeddedartists 5:f4de114c31c3 92 layers[i].lock = new Mutex();
embeddedartists 5:f4de114c31c3 93 layers[i].newData = NULL;
embeddedartists 5:f4de114c31c3 94 layers[i].activeData = NULL;
embeddedartists 5:f4de114c31c3 95 layers[i].fullscreen = false;
embeddedartists 5:f4de114c31c3 96 if ((xoff == 0) && (yoff == 0) && (width == screenWidth) && (height == screenHeight)) {
embeddedartists 5:f4de114c31c3 97 layers[i].fullscreen = true;
embeddedartists 5:f4de114c31c3 98 }
embeddedartists 5:f4de114c31c3 99
embeddedartists 5:f4de114c31c3 100 layers[i].tmp = (uint16_t*)malloc(width*layers[i].clippedHeight*2);
embeddedartists 5:f4de114c31c3 101 if (layers[i].tmp != NULL) {
embeddedartists 5:f4de114c31c3 102 memset(layers[i].tmp, 0, width*layers[i].clippedHeight*2);
embeddedartists 5:f4de114c31c3 103 }
embeddedartists 5:f4de114c31c3 104
embeddedartists 5:f4de114c31c3 105
embeddedartists 5:f4de114c31c3 106 // sort the order
embeddedartists 5:f4de114c31c3 107 for (int j = 0; j < MaxNumLayers; j++) {
embeddedartists 5:f4de114c31c3 108 if (order[j] == NULL) {
embeddedartists 5:f4de114c31c3 109 // no more layers so add the new one to the top
embeddedartists 5:f4de114c31c3 110 order[j] = &(layers[i]);
embeddedartists 5:f4de114c31c3 111 break;
embeddedartists 5:f4de114c31c3 112 }
embeddedartists 5:f4de114c31c3 113 if (order[j]->zorder > layer) {
embeddedartists 5:f4de114c31c3 114 // should insert the new layer here
embeddedartists 5:f4de114c31c3 115 for (int k = numRegisteredLayers; k > j; k--) {
embeddedartists 5:f4de114c31c3 116 order[k] = order[k-1];
embeddedartists 5:f4de114c31c3 117 }
embeddedartists 5:f4de114c31c3 118 order[j] = &(layers[i]);
embeddedartists 5:f4de114c31c3 119 break;
embeddedartists 5:f4de114c31c3 120 }
embeddedartists 5:f4de114c31c3 121 }
embeddedartists 5:f4de114c31c3 122
embeddedartists 5:f4de114c31c3 123 // Cause a repaint of all layers. It does not have to be immediate
embeddedartists 5:f4de114c31c3 124 // as for unregisterUser() - it is enough that it is done next time.
embeddedartists 5:f4de114c31c3 125 order[0]->activeData = NULL;
embeddedartists 5:f4de114c31c3 126
embeddedartists 5:f4de114c31c3 127 numRegisteredLayers++;
embeddedartists 5:f4de114c31c3 128
embeddedartists 5:f4de114c31c3 129 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 130 return (uint32_t)(&(layers[i]));
embeddedartists 5:f4de114c31c3 131 }
embeddedartists 5:f4de114c31c3 132 }
embeddedartists 5:f4de114c31c3 133 }
embeddedartists 5:f4de114c31c3 134 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 135 return 0;
embeddedartists 5:f4de114c31c3 136 }
embeddedartists 5:f4de114c31c3 137
embeddedartists 5:f4de114c31c3 138 uint32_t Renderer::registerFullscreenUser(int layer)
embeddedartists 5:f4de114c31c3 139 {
embeddedartists 5:f4de114c31c3 140 return registerUser(layer, 0, 0, screenWidth, screenHeight);
embeddedartists 5:f4de114c31c3 141 }
embeddedartists 5:f4de114c31c3 142
embeddedartists 5:f4de114c31c3 143 void Renderer::unregisterUser(uint32_t handle)
embeddedartists 5:f4de114c31c3 144 {
embeddedartists 5:f4de114c31c3 145 setupMutex.lock();
embeddedartists 5:f4de114c31c3 146 if (handle != 0) {
embeddedartists 5:f4de114c31c3 147 layerinfo_t* layer = (layerinfo_t*)handle;
embeddedartists 5:f4de114c31c3 148 for (int i = 0; i < MaxNumLayers; i++) {
embeddedartists 5:f4de114c31c3 149 if (order[i] == layer) {
embeddedartists 5:f4de114c31c3 150 layer->used = false;
embeddedartists 5:f4de114c31c3 151 free(layer->tmp);
embeddedartists 5:f4de114c31c3 152 delete layer->lock;
embeddedartists 5:f4de114c31c3 153
embeddedartists 5:f4de114c31c3 154 // move all layers "down" one step
embeddedartists 5:f4de114c31c3 155 for (int j = i+1; j<numRegisteredLayers; j++) {
embeddedartists 5:f4de114c31c3 156 order[j-1] = order[j];
embeddedartists 5:f4de114c31c3 157 }
embeddedartists 5:f4de114c31c3 158 order[numRegisteredLayers-1] = NULL;
embeddedartists 5:f4de114c31c3 159 numRegisteredLayers--;
embeddedartists 5:f4de114c31c3 160
embeddedartists 5:f4de114c31c3 161 // cause a repaint
embeddedartists 5:f4de114c31c3 162 if (order[0] != NULL) {
embeddedartists 5:f4de114c31c3 163 order[0]->activeData = NULL;
embeddedartists 5:f4de114c31c3 164
embeddedartists 5:f4de114c31c3 165 // Very important that the signal is not sent while the lock is held
embeddedartists 5:f4de114c31c3 166 // as it will cause the renderer thread be able to take it also
embeddedartists 5:f4de114c31c3 167 setupMutex.unlock();
embeddedartists 15:a68bb30ab95e 168 osSignalSet(threadId, layer->signalId);
embeddedartists 5:f4de114c31c3 169 return;
embeddedartists 5:f4de114c31c3 170 } else {
embeddedartists 5:f4de114c31c3 171 // no longer anything to show, clear back buffers
embeddedartists 5:f4de114c31c3 172 memset(ImageBackBuffer[0], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 173 memset(ImageBackBuffer[1], 0xff, screenBytes);
embeddedartists 5:f4de114c31c3 174 }
embeddedartists 5:f4de114c31c3 175
embeddedartists 5:f4de114c31c3 176 break;
embeddedartists 5:f4de114c31c3 177 }
embeddedartists 5:f4de114c31c3 178 }
embeddedartists 5:f4de114c31c3 179 }
embeddedartists 5:f4de114c31c3 180 setupMutex.unlock();
embeddedartists 5:f4de114c31c3 181 }
embeddedartists 5:f4de114c31c3 182
embeddedartists 5:f4de114c31c3 183 void Renderer::setFramebuffer(uint32_t handle, const uint16_t* data)
embeddedartists 5:f4de114c31c3 184 {
embeddedartists 5:f4de114c31c3 185 layerinfo_t* layer = (layerinfo_t*)handle;
embeddedartists 5:f4de114c31c3 186
embeddedartists 5:f4de114c31c3 187 // make sure that the render thread is not using the data when
embeddedartists 5:f4de114c31c3 188 // we change it
embeddedartists 5:f4de114c31c3 189 layer->lock->lock();
embeddedartists 5:f4de114c31c3 190 layer->newData = data;
embeddedartists 5:f4de114c31c3 191 layer->activeData = NULL;
embeddedartists 5:f4de114c31c3 192 layer->lock->unlock();
embeddedartists 5:f4de114c31c3 193
embeddedartists 5:f4de114c31c3 194 // notify the renderer that there is new data for our layer
embeddedartists 15:a68bb30ab95e 195 osSignalSet(threadId, layer->signalId);
embeddedartists 5:f4de114c31c3 196 }
embeddedartists 5:f4de114c31c3 197
embeddedartists 5:f4de114c31c3 198 void Renderer::render()
embeddedartists 5:f4de114c31c3 199 {
embeddedartists 15:a68bb30ab95e 200 //save this thread's ID so that it may be signalled from
embeddedartists 15:a68bb30ab95e 201 //unregisterUser() and setFramebuffer()
embeddedartists 21:0038059e3a8f 202 threadId = ThisThread::get_id();
embeddedartists 15:a68bb30ab95e 203
embeddedartists 5:f4de114c31c3 204 int mask = 1;//(1<<MaxNumLayers) - 1;
embeddedartists 5:f4de114c31c3 205 while(true)
embeddedartists 5:f4de114c31c3 206 {
embeddedartists 21:0038059e3a8f 207 /*osEvent ev =*/ ThisThread::flags_wait_any(mask);
embeddedartists 21:0038059e3a8f 208 /*if (ev.status == osEventSignal) {*/
embeddedartists 5:f4de114c31c3 209 setupMutex.lock();
embeddedartists 5:f4de114c31c3 210 for (int i = 0; i < numRegisteredLayers; i++) {
embeddedartists 5:f4de114c31c3 211 if (order[i]->activeData != order[i]->newData) {
embeddedartists 5:f4de114c31c3 212 //if (order[i]->signalId & ev.value.signals) {
embeddedartists 5:f4de114c31c3 213
embeddedartists 5:f4de114c31c3 214 int n = (activeBackBuffer + 1) & 1;
embeddedartists 5:f4de114c31c3 215
embeddedartists 5:f4de114c31c3 216 // if (i == 0) {
embeddedartists 5:f4de114c31c3 217 // // TEMPORARY
embeddedartists 5:f4de114c31c3 218 // board->setFrameBuffer((uint32_t)ImageBackBuffer[n]);
embeddedartists 5:f4de114c31c3 219 // if (order[i]->activeData != NULL && order[i]->newData != NULL) {
embeddedartists 5:f4de114c31c3 220 // for (int y = 0; y < order[i]->clippedHeight; y++) {
embeddedartists 5:f4de114c31c3 221 // for (int x = 0; x < order[i]->width; x++) {
embeddedartists 5:f4de114c31c3 222 // if (order[i]->activeData[y*order[i]->width+x] != order[i]->newData[y*order[i]->width+x]) {
embeddedartists 5:f4de114c31c3 223 // printf("Difference in x,y {%d,%d} active is 0x%04x, new is 0x%04x\n", x, y,
embeddedartists 5:f4de114c31c3 224 // order[i]->activeData[y*order[i]->width+x], order[i]->newData[y*order[i]->width+x]);
embeddedartists 5:f4de114c31c3 225 // }
embeddedartists 5:f4de114c31c3 226 // }
embeddedartists 5:f4de114c31c3 227 // }
embeddedartists 5:f4de114c31c3 228 // }
embeddedartists 5:f4de114c31c3 229 // }
embeddedartists 5:f4de114c31c3 230
embeddedartists 5:f4de114c31c3 231 // Layer i have new data
embeddedartists 5:f4de114c31c3 232 // redraw this layer and all on top of it
embeddedartists 5:f4de114c31c3 233 for (int j = i; j < numRegisteredLayers; j++) {
embeddedartists 5:f4de114c31c3 234 layerinfo_t* layer = order[j];
embeddedartists 5:f4de114c31c3 235 layer->lock->lock();
embeddedartists 5:f4de114c31c3 236 layer->activeData = layer->newData;
embeddedartists 5:f4de114c31c3 237 memcpy(layer->tmp, layer->newData, layer->width*layer->clippedHeight*2);
embeddedartists 5:f4de114c31c3 238 layer->lock->unlock();
embeddedartists 5:f4de114c31c3 239 if (layer->activeData != NULL) {
embeddedartists 5:f4de114c31c3 240 if (layer->fullscreen) {
embeddedartists 5:f4de114c31c3 241 memcpy(ImageBackBuffer[n], layer->tmp, screenBytes);
embeddedartists 5:f4de114c31c3 242 } else {
embeddedartists 5:f4de114c31c3 243 for (int y = 0; y < layer->clippedHeight; y++) {
embeddedartists 5:f4de114c31c3 244 memcpy(ImageBackBuffer[n] + ((y + layer->y0) * screenWidth) + layer->x0,
embeddedartists 5:f4de114c31c3 245 layer->tmp + (y * layer->width),
embeddedartists 5:f4de114c31c3 246 (layer->x1 - layer->x0) * 2);
embeddedartists 5:f4de114c31c3 247 }
embeddedartists 5:f4de114c31c3 248 }
embeddedartists 5:f4de114c31c3 249 }
embeddedartists 5:f4de114c31c3 250 }
embeddedartists 5:f4de114c31c3 251
embeddedartists 5:f4de114c31c3 252 //board->setFrameBuffer((uint32_t)ImageBackBuffer[n]);
embeddedartists 5:f4de114c31c3 253 display->setFramebuffer(ImageBackBuffer[n]);
embeddedartists 5:f4de114c31c3 254 if (i == (numRegisteredLayers - 1)) {
embeddedartists 5:f4de114c31c3 255 // only top layer changed, no need to copy entire back buffer
embeddedartists 5:f4de114c31c3 256 } else {
embeddedartists 5:f4de114c31c3 257 // more layers exist on top so the back buffer must be updated
embeddedartists 5:f4de114c31c3 258 memcpy(ImageBackBuffer[activeBackBuffer], ImageBackBuffer[n], screenBytes);
embeddedartists 5:f4de114c31c3 259 }
embeddedartists 5:f4de114c31c3 260 activeBackBuffer = n;
embeddedartists 5:f4de114c31c3 261 break;
embeddedartists 5:f4de114c31c3 262 }
embeddedartists 5:f4de114c31c3 263 }
embeddedartists 5:f4de114c31c3 264 setupMutex.unlock();
embeddedartists 21:0038059e3a8f 265 /*}*/
embeddedartists 5:f4de114c31c3 266 }
embeddedartists 5:f4de114c31c3 267 }