Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DMBasicGUI by
Renderer.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "Renderer.h" 00019 #include "DMBoard.h" 00020 00021 /****************************************************************************** 00022 * Defines and typedefs 00023 *****************************************************************************/ 00024 00025 #if !defined(MIN) 00026 #define MIN(__a, __b) (((__a)<(__b))?(__a):(__b)) 00027 #endif 00028 00029 /****************************************************************************** 00030 * Public functions 00031 *****************************************************************************/ 00032 00033 Renderer::Renderer() 00034 { 00035 memset(layers, 0, sizeof(layerinfo_t)*MaxNumLayers); 00036 for (int i = 0; i < MaxNumLayers; i++) { 00037 layers[i].used = false; 00038 order[i] = NULL; 00039 } 00040 00041 numRegisteredLayers = 0; 00042 activeBackBuffer = 0; 00043 display = DMBoard::instance().display(); 00044 00045 this->screenWidth = display->width(); 00046 this->screenHeight = display->height(); 00047 this->screenPixels = this->screenWidth * this->screenHeight; 00048 00049 // Assume screen->bpp == Bpp_16 00050 this->screenBytes = display->bytesPerPixel() * this->screenPixels; 00051 00052 ImageBackBuffer[0] = (image_t)display->allocateFramebuffer(); 00053 ImageBackBuffer[1] = (image_t)display->allocateFramebuffer(); 00054 if ((ImageBackBuffer[0] == NULL) || (ImageBackBuffer[1] == NULL)) { 00055 printf("Failed to allocate buffer(s) for Renderer. Halting...\n"); 00056 while(1) { 00057 ; 00058 } 00059 } 00060 memset(ImageBackBuffer[0], 0xff, screenBytes); 00061 memset(ImageBackBuffer[1], 0xff, screenBytes); 00062 } 00063 00064 Renderer::~Renderer() 00065 { 00066 free(ImageBackBuffer[0]); 00067 free(ImageBackBuffer[1]); 00068 for (int i = 0; i < MaxNumLayers; i++) { 00069 if (layers[i].used) { 00070 free(layers[i].tmp); 00071 delete(layers[i].lock); 00072 } 00073 } 00074 } 00075 00076 uint32_t Renderer::registerUser(int layer, int xoff, int yoff, int width, int height) 00077 { 00078 setupMutex.lock(); 00079 if (numRegisteredLayers < MaxNumLayers) { 00080 for (int i = 0; i < MaxNumLayers; i++) { 00081 if (!layers[i].used) { 00082 // found a spot 00083 layers[i].used = true; 00084 layers[i].x0 = xoff; 00085 layers[i].y0 = yoff; 00086 layers[i].x1 = MIN(xoff+width, screenWidth); 00087 layers[i].y1 = MIN(yoff+height, screenHeight); 00088 layers[i].width = width; 00089 layers[i].clippedHeight = layers[i].y1 - layers[i].y0; 00090 layers[i].zorder = layer; 00091 layers[i].signalId = 1;//(1<<i); 00092 layers[i].lock = new Mutex(); 00093 layers[i].newData = NULL; 00094 layers[i].activeData = NULL; 00095 layers[i].fullscreen = false; 00096 if ((xoff == 0) && (yoff == 0) && (width == screenWidth) && (height == screenHeight)) { 00097 layers[i].fullscreen = true; 00098 } 00099 00100 layers[i].tmp = (uint16_t*)malloc(width*layers[i].clippedHeight*2); 00101 if (layers[i].tmp != NULL) { 00102 memset(layers[i].tmp, 0, width*layers[i].clippedHeight*2); 00103 } 00104 00105 00106 // sort the order 00107 for (int j = 0; j < MaxNumLayers; j++) { 00108 if (order[j] == NULL) { 00109 // no more layers so add the new one to the top 00110 order[j] = &(layers[i]); 00111 break; 00112 } 00113 if (order[j]->zorder > layer) { 00114 // should insert the new layer here 00115 for (int k = numRegisteredLayers; k > j; k--) { 00116 order[k] = order[k-1]; 00117 } 00118 order[j] = &(layers[i]); 00119 break; 00120 } 00121 } 00122 00123 // Cause a repaint of all layers. It does not have to be immediate 00124 // as for unregisterUser() - it is enough that it is done next time. 00125 order[0]->activeData = NULL; 00126 00127 numRegisteredLayers++; 00128 00129 setupMutex.unlock(); 00130 return (uint32_t)(&(layers[i])); 00131 } 00132 } 00133 } 00134 setupMutex.unlock(); 00135 return 0; 00136 } 00137 00138 uint32_t Renderer::registerFullscreenUser(int layer) 00139 { 00140 return registerUser(layer, 0, 0, screenWidth, screenHeight); 00141 } 00142 00143 void Renderer::unregisterUser(uint32_t handle) 00144 { 00145 setupMutex.lock(); 00146 if (handle != 0) { 00147 layerinfo_t* layer = (layerinfo_t*)handle; 00148 for (int i = 0; i < MaxNumLayers; i++) { 00149 if (order[i] == layer) { 00150 layer->used = false; 00151 free(layer->tmp); 00152 delete layer->lock; 00153 00154 // move all layers "down" one step 00155 for (int j = i+1; j<numRegisteredLayers; j++) { 00156 order[j-1] = order[j]; 00157 } 00158 order[numRegisteredLayers-1] = NULL; 00159 numRegisteredLayers--; 00160 00161 // cause a repaint 00162 if (order[0] != NULL) { 00163 order[0]->activeData = NULL; 00164 00165 // Very important that the signal is not sent while the lock is held 00166 // as it will cause the renderer thread be able to take it also 00167 setupMutex.unlock(); 00168 osSignalSet(threadId, layer->signalId); 00169 return; 00170 } else { 00171 // no longer anything to show, clear back buffers 00172 memset(ImageBackBuffer[0], 0xff, screenBytes); 00173 memset(ImageBackBuffer[1], 0xff, screenBytes); 00174 } 00175 00176 break; 00177 } 00178 } 00179 } 00180 setupMutex.unlock(); 00181 } 00182 00183 void Renderer::setFramebuffer(uint32_t handle, const uint16_t* data) 00184 { 00185 layerinfo_t* layer = (layerinfo_t*)handle; 00186 00187 // make sure that the render thread is not using the data when 00188 // we change it 00189 layer->lock->lock(); 00190 layer->newData = data; 00191 layer->activeData = NULL; 00192 layer->lock->unlock(); 00193 00194 // notify the renderer that there is new data for our layer 00195 osSignalSet(threadId, layer->signalId); 00196 } 00197 00198 void Renderer::render() 00199 { 00200 //save this thread's ID so that it may be signalled from 00201 //unregisterUser() and setFramebuffer() 00202 threadId = Thread::gettid(); 00203 00204 int mask = 1;//(1<<MaxNumLayers) - 1; 00205 while(true) 00206 { 00207 osEvent ev = Thread::signal_wait(mask); 00208 if (ev.status == osEventSignal) { 00209 setupMutex.lock(); 00210 for (int i = 0; i < numRegisteredLayers; i++) { 00211 if (order[i]->activeData != order[i]->newData) { 00212 //if (order[i]->signalId & ev.value.signals) { 00213 00214 int n = (activeBackBuffer + 1) & 1; 00215 00216 // if (i == 0) { 00217 // // TEMPORARY 00218 // board->setFrameBuffer((uint32_t)ImageBackBuffer[n]); 00219 // if (order[i]->activeData != NULL && order[i]->newData != NULL) { 00220 // for (int y = 0; y < order[i]->clippedHeight; y++) { 00221 // for (int x = 0; x < order[i]->width; x++) { 00222 // if (order[i]->activeData[y*order[i]->width+x] != order[i]->newData[y*order[i]->width+x]) { 00223 // printf("Difference in x,y {%d,%d} active is 0x%04x, new is 0x%04x\n", x, y, 00224 // order[i]->activeData[y*order[i]->width+x], order[i]->newData[y*order[i]->width+x]); 00225 // } 00226 // } 00227 // } 00228 // } 00229 // } 00230 00231 // Layer i have new data 00232 // redraw this layer and all on top of it 00233 for (int j = i; j < numRegisteredLayers; j++) { 00234 layerinfo_t* layer = order[j]; 00235 layer->lock->lock(); 00236 layer->activeData = layer->newData; 00237 memcpy(layer->tmp, layer->newData, layer->width*layer->clippedHeight*2); 00238 layer->lock->unlock(); 00239 if (layer->activeData != NULL) { 00240 if (layer->fullscreen) { 00241 memcpy(ImageBackBuffer[n], layer->tmp, screenBytes); 00242 } else { 00243 for (int y = 0; y < layer->clippedHeight; y++) { 00244 memcpy(ImageBackBuffer[n] + ((y + layer->y0) * screenWidth) + layer->x0, 00245 layer->tmp + (y * layer->width), 00246 (layer->x1 - layer->x0) * 2); 00247 } 00248 } 00249 } 00250 } 00251 00252 //board->setFrameBuffer((uint32_t)ImageBackBuffer[n]); 00253 display->setFramebuffer(ImageBackBuffer[n]); 00254 if (i == (numRegisteredLayers - 1)) { 00255 // only top layer changed, no need to copy entire back buffer 00256 } else { 00257 // more layers exist on top so the back buffer must be updated 00258 memcpy(ImageBackBuffer[activeBackBuffer], ImageBackBuffer[n], screenBytes); 00259 } 00260 activeBackBuffer = n; 00261 break; 00262 } 00263 } 00264 setupMutex.unlock(); 00265 } 00266 } 00267 }
Generated on Wed Jul 13 2022 03:01:51 by
1.7.2
