FabGL
ESP32 Display Controller and Graphics Library
cvbsbasecontroller.cpp
1/*
2 Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - <http://www.fabgl.com>
3 Copyright (c) 2019-2022 Fabrizio Di Vittorio.
4 All rights reserved.
5
6
7* Please contact fdivitto2013@gmail.com if you need a commercial license.
8
9
10* This library and related software is available under GPL v3.
11
12 FabGL is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 FabGL is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with FabGL. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26
27
28#include <alloca.h>
29#include <stdarg.h>
30#include <math.h>
31#include <string.h>
32
33#include "freertos/FreeRTOS.h"
34#include "freertos/task.h"
35
36#include "fabutils.h"
37#include "devdrivers/cvbsgenerator.h"
39
40
41#pragma GCC optimize ("O2")
42
43
44namespace fabgl {
45
46
47CVBSBaseController::CVBSBaseController()
48 : m_horizontalRate(1)
49{
50}
51
52
53void CVBSBaseController::init()
54{
55 m_primitiveProcessingSuspended = 1; // >0 suspended
56 m_viewPort = nullptr;
57 m_viewPortMemoryPool[0] = nullptr;
58}
59
60
61void CVBSBaseController::begin(gpio_num_t videoGPIO)
62{
63 init();
64 m_CVBSGenerator.setVideoGPIO(videoGPIO);
65}
66
67
68void CVBSBaseController::begin()
69{
70 begin(GPIO_NUM_25);
71}
72
73
74void CVBSBaseController::end()
75{
76 m_CVBSGenerator.stop();
77}
78
79
80void CVBSBaseController::freeViewPort()
81{
82 for (uint8_t * * poolPtr = m_viewPortMemoryPool; *poolPtr; ++poolPtr) {
83 heap_caps_free((void*) *poolPtr);
84 *poolPtr = nullptr;
85 }
86 if (m_viewPort) {
87 heap_caps_free(m_viewPort);
88 m_viewPort = nullptr;
89 }
90 if (isDoubleBuffered())
91 heap_caps_free(m_viewPortVisible);
92 m_viewPortVisible = nullptr;
93}
94
95
96// Warning: After call to suspendBackgroundPrimitiveExecution() adding primitives may cause a deadlock.
97// To avoid this a call to "processPrimitives()" should be performed very often.
98// Can be nested
99void CVBSBaseController::suspendBackgroundPrimitiveExecution()
100{
101 ++m_primitiveProcessingSuspended;
102}
103
104
105// Resume after suspendBackgroundPrimitiveExecution()
106// Can be nested
107void CVBSBaseController::resumeBackgroundPrimitiveExecution()
108{
109 m_primitiveProcessingSuspended = tmax(0, m_primitiveProcessingSuspended - 1);
110}
111
112
113void CVBSBaseController::setResolution(char const * modeline, int viewPortWidth, int viewPortHeight, bool doubleBuffered)
114{
115 auto params = CVBSGenerator::getParamsFromDesc(modeline);
116 if (params)
117 setResolution(params, viewPortWidth, viewPortHeight);
118}
119
120
121void CVBSBaseController::setResolution(CVBSParams const * params, int viewPortWidth, int viewPortHeight, bool doubleBuffered)
122{
123 // just in case setResolution() was called before
124 end();
125
126 m_CVBSGenerator.setup(params);
127
128 m_viewPortWidth = viewPortWidth < 0 ? m_CVBSGenerator.visibleSamples() : viewPortWidth;
129 m_viewPortHeight = viewPortHeight < 0 ? m_CVBSGenerator.visibleLines() * m_CVBSGenerator.params()->interlaceFactor : viewPortHeight;
130
131 // reduce viewport if more than one sample per color is required
132 m_viewPortWidth /= m_horizontalRate;
133
134 // inform base class about screen size
135 setScreenSize(m_viewPortWidth, m_viewPortHeight);
136
137 setDoubleBuffered(doubleBuffered);
138
139 // adjust view port size if necessary
140 checkViewPortSize();
141
142 // allocate the viewport
143 allocateViewPort();
144
145 // adjust again view port size if necessary
146 checkViewPortSize();
147
148 resetPaintState();
149}
150
151
152void CVBSBaseController::run()
153{
154 m_CVBSGenerator.run();
155}
156
157
158// this method may adjust m_viewPortHeight to the actual number of allocated rows.
159// to reduce memory allocation overhead try to allocate the minimum number of blocks.
160void CVBSBaseController::allocateViewPort(uint32_t allocCaps, int rowlen)
161{
162 int linesCount[FABGLIB_VIEWPORT_MEMORY_POOL_COUNT]; // where store number of lines for each pool
163 int poolsCount = 0; // number of allocated pools
164 int remainingLines = m_viewPortHeight;
165 m_viewPortHeight = 0; // m_viewPortHeight needs to be recalculated
166
167 if (isDoubleBuffered())
168 remainingLines *= 2;
169
170 // allocate pools
171 while (remainingLines > 0 && poolsCount < FABGLIB_VIEWPORT_MEMORY_POOL_COUNT) {
172 int largestBlock = heap_caps_get_largest_free_block(allocCaps);
173 linesCount[poolsCount] = tmin(remainingLines, largestBlock / rowlen);
174 if (linesCount[poolsCount] == 0) // no more memory available for lines
175 break;
176 m_viewPortMemoryPool[poolsCount] = (uint8_t*) heap_caps_malloc(linesCount[poolsCount] * rowlen, allocCaps);
177 remainingLines -= linesCount[poolsCount];
178 m_viewPortHeight += linesCount[poolsCount];
179 ++poolsCount;
180 }
181 m_viewPortMemoryPool[poolsCount] = nullptr;
182
183 // fill m_viewPort[] with line pointers
184 if (isDoubleBuffered()) {
185 m_viewPortHeight /= 2;
186 m_viewPortVisible = (volatile uint8_t * *) heap_caps_malloc(sizeof(uint8_t*) * m_viewPortHeight, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL);
187 }
188 m_viewPort = (volatile uint8_t * *) heap_caps_malloc(sizeof(uint8_t*) * m_viewPortHeight, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL);
189 if (!isDoubleBuffered())
190 m_viewPortVisible = m_viewPort;
191 for (int p = 0, l = 0; p < poolsCount; ++p) {
192 uint8_t * pool = m_viewPortMemoryPool[p];
193 for (int i = 0; i < linesCount[p]; ++i) {
194 if (l + i < m_viewPortHeight)
195 m_viewPort[l + i] = pool;
196 else
197 m_viewPortVisible[l + i - m_viewPortHeight] = pool; // set only when double buffered is enabled
198 pool += rowlen;
199 }
200 l += linesCount[p];
201 }
202}
203
204
205void IRAM_ATTR CVBSBaseController::swapBuffers()
206{
207 tswap(m_viewPort, m_viewPortVisible);
208}
209
210
211
212
213} // end of namespace
214
215
This file contains fabgl::CVBSBaseController definition.
#define FABGLIB_VIEWPORT_MEMORY_POOL_COUNT
Definition: fabglconf.h:126
This file contains some utility classes and functions.