@geastack/core 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +36 -0
- package/app_frame_perf.cpp +77 -0
- package/css.d.ts +1 -0
- package/events.cpp +67 -0
- package/gea_app_entry.cpp +317 -0
- package/gea_sources.mjs +126 -0
- package/gea_sources.sh +36 -0
- package/include/app.h +60 -0
- package/include/apps.h +46 -0
- package/include/audio.h +90 -0
- package/include/ble.h +212 -0
- package/include/bluetooth/hid_profile.h +92 -0
- package/include/camera.h +107 -0
- package/include/canvas.h +290 -0
- package/include/display.h +390 -0
- package/include/display_present.h +869 -0
- package/include/event.h +32 -0
- package/include/events.h +116 -0
- package/include/gea/embedded.h +13 -0
- package/include/gea/reactive_runtime.h +32 -0
- package/include/gea.h +14 -0
- package/include/gea_perf_config.h +96 -0
- package/include/geaos/abi.h +165 -0
- package/include/geolocation.h +126 -0
- package/include/gpio.h +61 -0
- package/include/graphics/font.h +122 -0
- package/include/i2c.h +20 -0
- package/include/image.h +156 -0
- package/include/imu.h +23 -0
- package/include/input.h +33 -0
- package/include/memory.h +52 -0
- package/include/pixel.h +907 -0
- package/include/platform/file_cache.h +18 -0
- package/include/power.h +11 -0
- package/include/runtime.h +83 -0
- package/include/services/app_runner.h +10 -0
- package/include/services/app_state.h +14 -0
- package/include/services/battery_service.h +12 -0
- package/include/services/bluetooth_service.h +13 -0
- package/include/services/diagnostics.h +76 -0
- package/include/services/diagnostics_platform.h +54 -0
- package/include/services/frame_scheduler.h +71 -0
- package/include/services/mirror.h +49 -0
- package/include/services/network_services.h +25 -0
- package/include/services/ota.h +32 -0
- package/include/services/runtime_log.h +11 -0
- package/include/services/storage_service.h +26 -0
- package/include/touch.h +38 -0
- package/include/ui/signal.h +149 -0
- package/include/wifi.h +67 -0
- package/index.d.ts +1940 -0
- package/jsx.d.ts +1 -0
- package/package.json +70 -0
- package/runtime/ble.ts +49 -0
- package/runtime/color.ts +21 -0
- package/runtime/compiler.ts +43 -0
- package/runtime/host.ts +1083 -0
- package/runtime/images.ts +129 -0
- package/runtime/primitives.ts +49 -0
- package/runtime-surface.ts +180 -0
- package/runtime.cpp +431 -0
- package/runtime.ts +34 -0
- package/scripts/build-gea-vite-geatsc.mjs +4514 -0
- package/scripts/dotenv-defines.mjs +98 -0
- package/scripts/gea-bundle-type-hints.mjs +546 -0
- package/scripts/gea-embedded-compat-staging.mjs +17 -0
- package/scripts/gea-embedded-compat-transform.mjs +427 -0
- package/scripts/gea-vite-module-graph-plugin.mjs +578 -0
- package/scripts/generate-gea-embedded-assets.mjs +296 -0
- package/scripts/generate-gea-embedded-fonts.mjs +1252 -0
- package/scripts/generate-installed-app-plan.mjs +55 -0
- package/scripts/native-object-cache.sh +244 -0
package/include/canvas.h
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "pixel.h"
|
|
4
|
+
|
|
5
|
+
#include <cstddef>
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
|
|
8
|
+
namespace gea::framework::graphics {
|
|
9
|
+
|
|
10
|
+
class RasterizedFont;
|
|
11
|
+
|
|
12
|
+
struct ClipRect {
|
|
13
|
+
int x0 = 0;
|
|
14
|
+
int y0 = 0;
|
|
15
|
+
int x1 = 0;
|
|
16
|
+
int y1 = 0;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
struct CanvasDirtyRect {
|
|
20
|
+
int x0 = 0;
|
|
21
|
+
int y0 = 0;
|
|
22
|
+
int x1 = -1;
|
|
23
|
+
int y1 = -1;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Interleaved circle record used by fillCirclesRgb565WorldYSorted. Field order
|
|
27
|
+
// is (y, x, color) so sorting an array of these by ::y is a simple
|
|
28
|
+
// std::sort with a single comparator on the first field. The display_present
|
|
29
|
+
// pipeline allocates these in INTERNAL RAM, sorts in place, and hands the
|
|
30
|
+
// pointer directly to Canvas — no deinterleave step.
|
|
31
|
+
struct CircleEntry {
|
|
32
|
+
std::uint16_t y;
|
|
33
|
+
std::uint16_t x;
|
|
34
|
+
pixel::native_t color;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Interleaved opaque-triangle record used by the batched triangle present
|
|
38
|
+
// command (one command per frame instead of one per triangle — the per-command
|
|
39
|
+
// record/dispatch overhead dominated at a few hundred triangles). Kept in
|
|
40
|
+
// PAINTER'S order (depth-sorted by the producer), so the rasterizer may only
|
|
41
|
+
// band-reject per entry, never reorder. rowY0/rowY1 cache the vertical extent
|
|
42
|
+
// for that reject. int16 coordinates: producers clamp to +/-30000.
|
|
43
|
+
struct TriangleEntry {
|
|
44
|
+
std::int16_t x0;
|
|
45
|
+
std::int16_t y0;
|
|
46
|
+
std::int16_t x1;
|
|
47
|
+
std::int16_t y1;
|
|
48
|
+
std::int16_t x2;
|
|
49
|
+
std::int16_t y2;
|
|
50
|
+
pixel::native_t color;
|
|
51
|
+
std::int16_t rowY0;
|
|
52
|
+
std::int16_t rowY1;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
class Canvas {
|
|
56
|
+
public:
|
|
57
|
+
static constexpr int kMaxClipDepth = 32;
|
|
58
|
+
static constexpr int kMaxDirtyRects = 24;
|
|
59
|
+
static void setAntialiasSamples(int samples);
|
|
60
|
+
static int antialiasSamples();
|
|
61
|
+
// Large-static-text sprite cache opt-in (default off). When enabled, text at
|
|
62
|
+
// font.sizePx() >= 40 is rasterized to a coverage sprite once and blitted on
|
|
63
|
+
// subsequent frames instead of re-running the glyph rasterizer. Toggled from
|
|
64
|
+
// TS via Display.setTextRasterCache(boolean).
|
|
65
|
+
static void setTextRasterCacheEnabled(bool enabled);
|
|
66
|
+
static bool textRasterCacheEnabled();
|
|
67
|
+
// Pre-packed glyph stamping opt-in (packed 4bpp targets; no-op elsewhere).
|
|
68
|
+
// The app declares text always draws over ONE solid color (0xRRGGBB);
|
|
69
|
+
// glyphs are then pre-blended+packed once and stamped as byte copies — no
|
|
70
|
+
// per-pixel destination read, no blend. Negative disables. Toggled from TS
|
|
71
|
+
// via Display.setTextSolidBackdrop(number).
|
|
72
|
+
static void setTextSolidBackdrop(int rrggbb);
|
|
73
|
+
|
|
74
|
+
// `pixel::native_t` is this target's framebuffer pixel (RGB565 16-bit or
|
|
75
|
+
// RGBA8888 32-bit), fixed at compile time — no runtime format here.
|
|
76
|
+
void bindPixels(pixel::native_t *pixels, int width, int height);
|
|
77
|
+
void bindPixels(pixel::native_t *pixels, int width, int height, int stridePixels);
|
|
78
|
+
|
|
79
|
+
#if GEA_EMBEDDED_DISPLAY_ROTATE_LANDSCAPE
|
|
80
|
+
// Bind a PHYSICAL landscape buffer while presenting a LOGICAL portrait
|
|
81
|
+
// coordinate system. The apps + renderer keep drawing in logical portrait
|
|
82
|
+
// (logicalWidth x logicalHeight); every pixel write is rotated 90° into the
|
|
83
|
+
// physical landscape buffer, whose dimensions are (logicalHeight x
|
|
84
|
+
// logicalWidth). A logical pixel (lx, ly) addresses physical column ly, row
|
|
85
|
+
// (logicalWidth-1)-lx — the same map the papers3/T5 flush-time transpose used,
|
|
86
|
+
// so the Canvas IS the panel buffer and no separate transpose pass is needed.
|
|
87
|
+
// Additive and compile-gated: only built when GEA_EMBEDDED_DISPLAY_ROTATE_
|
|
88
|
+
// LANDSCAPE is defined (papers3), so every other target is byte-for-byte
|
|
89
|
+
// unaffected. Supports both packed grayscale and native RGB framebuffers.
|
|
90
|
+
void bindPixelsRotatedLandscape(pixel::native_t *physPixels, int logicalWidth, int logicalHeight);
|
|
91
|
+
#endif
|
|
92
|
+
|
|
93
|
+
pixel::native_t *pixels();
|
|
94
|
+
const pixel::native_t *pixels() const;
|
|
95
|
+
int width() const;
|
|
96
|
+
int height() const;
|
|
97
|
+
int strideBytes() const;
|
|
98
|
+
|
|
99
|
+
// Software-scroll register: rotates the logical → physical row mapping
|
|
100
|
+
// inside a scroll region without moving any pixels. A pixel write at
|
|
101
|
+
// logical row Y lands at the physical FB row determined by the region:
|
|
102
|
+
// - outside the region (y < regionY or y >= regionY+regionH): no
|
|
103
|
+
// translation, physical row = y.
|
|
104
|
+
// - inside the region: physical row = regionY + ((y − regionY +
|
|
105
|
+
// scrollOffsetY) mod regionH). Wraps inside the region's row range
|
|
106
|
+
// so the region acts as a ring buffer along Y.
|
|
107
|
+
// regionH = 0 means "no region active" — every pixel writes through.
|
|
108
|
+
// A scroll becomes a single integer update on scrollOffsetY rather than
|
|
109
|
+
// an H × W memcpy.
|
|
110
|
+
void setScrollRegion(int regionY, int regionH, int scrollOffsetY);
|
|
111
|
+
int scrollOffsetY() const { return scrollOffsetY_; }
|
|
112
|
+
int scrollRegionY() const { return regionY_; }
|
|
113
|
+
int scrollRegionH() const { return regionH_; }
|
|
114
|
+
int rowToPhysical(int y) const {
|
|
115
|
+
if (regionH_ <= 0) return y;
|
|
116
|
+
if (y < regionY_ || y >= regionY_ + regionH_) return y;
|
|
117
|
+
int rel = (y - regionY_) + scrollOffsetY_;
|
|
118
|
+
rel %= regionH_;
|
|
119
|
+
if (rel < 0) rel += regionH_;
|
|
120
|
+
return regionY_ + rel;
|
|
121
|
+
}
|
|
122
|
+
#if GEA_PIXEL_STORAGE_PACKED
|
|
123
|
+
// Base of a physical row's packed bytes (sub-byte framebuffers only — GRAY4
|
|
124
|
+
// at 2 px/byte, GRAY2 at 4 px/byte; strideBytes_ carries the depth).
|
|
125
|
+
std::uint8_t *packedRow(int phys) {
|
|
126
|
+
return reinterpret_cast<std::uint8_t *>(pixels_) + static_cast<std::size_t>(phys) * strideBytes_;
|
|
127
|
+
}
|
|
128
|
+
const std::uint8_t *packedRow(int phys) const {
|
|
129
|
+
return reinterpret_cast<const std::uint8_t *>(pixels_) + static_cast<std::size_t>(phys) * strideBytes_;
|
|
130
|
+
}
|
|
131
|
+
#endif
|
|
132
|
+
#if GEA_EMBEDDED_DISPLAY_ROTATE_LANDSCAPE
|
|
133
|
+
// Landscape-rotation primitives (see bindPixelsRotatedLandscape). A LOGICAL
|
|
134
|
+
// pixel (lx, ly) maps to physical row (width_-1)-lx, physical column ly. These
|
|
135
|
+
// are the SINGLE place the rotation transform lives; every rotated Canvas draw
|
|
136
|
+
// path routes its pixel writes through them, so the transform is verified once.
|
|
137
|
+
bool landscapeRot_ = false;
|
|
138
|
+
int rotPhysRow(int lx) const { return (width_ - 1) - lx; }
|
|
139
|
+
void rotSet(int lx, int ly, pixel::native_t v) {
|
|
140
|
+
#if GEA_PIXEL_STORAGE_PACKED
|
|
141
|
+
pixel::packed::set(packedRow(rotPhysRow(lx)), ly, v);
|
|
142
|
+
#else
|
|
143
|
+
pixels_[rotPhysRow(lx) * stride_ + ly] = v;
|
|
144
|
+
#endif
|
|
145
|
+
}
|
|
146
|
+
void rotBlend(int lx, int ly, pixel::native_t fg, int alpha) {
|
|
147
|
+
#if GEA_PIXEL_STORAGE_PACKED
|
|
148
|
+
pixel::packed::blendPixel(packedRow(rotPhysRow(lx)), ly, fg, alpha);
|
|
149
|
+
#else
|
|
150
|
+
pixel::native_t &dst = pixels_[rotPhysRow(lx) * stride_ + ly];
|
|
151
|
+
dst = pixel::blendNative(fg, dst, alpha);
|
|
152
|
+
#endif
|
|
153
|
+
}
|
|
154
|
+
pixel::native_t rotGet(int lx, int ly) const {
|
|
155
|
+
#if GEA_PIXEL_STORAGE_PACKED
|
|
156
|
+
return pixel::packed::get(packedRow(rotPhysRow(lx)), ly);
|
|
157
|
+
#else
|
|
158
|
+
return pixels_[rotPhysRow(lx) * stride_ + ly];
|
|
159
|
+
#endif
|
|
160
|
+
}
|
|
161
|
+
#endif
|
|
162
|
+
|
|
163
|
+
void resetDirty();
|
|
164
|
+
void markDirty(int x0, int y0, int x1, int y1);
|
|
165
|
+
bool dirty(int *x0, int *y0, int *x1, int *y1) const;
|
|
166
|
+
int dirtyRects(CanvasDirtyRect *rects, int capacity) const;
|
|
167
|
+
|
|
168
|
+
void resetClip();
|
|
169
|
+
void pushClip(int x, int y, int w, int h);
|
|
170
|
+
void popClip();
|
|
171
|
+
void currentClip(int *x0, int *y0, int *x1, int *y1) const;
|
|
172
|
+
|
|
173
|
+
void setGlobalAlpha(std::uint8_t alpha);
|
|
174
|
+
std::uint8_t globalAlpha() const;
|
|
175
|
+
|
|
176
|
+
void clear(pixel::native_t color);
|
|
177
|
+
void clearRect(int x, int y, int w, int h);
|
|
178
|
+
void scrollRect(int x, int y, int w, int h, int dx, int dy);
|
|
179
|
+
void fillRect(int x, int y, int w, int h, pixel::native_t color);
|
|
180
|
+
void fillRectOpaque(int x, int y, int w, int h, pixel::native_t color);
|
|
181
|
+
void strokeRect(int x, int y, int w, int h, pixel::native_t color);
|
|
182
|
+
void fillCircle(int cx, int cy, int r, pixel::native_t color);
|
|
183
|
+
void fillCirclesRgb565(const std::uint16_t *xs, const std::uint16_t *ys, int count, int r, const pixel::native_t *colors);
|
|
184
|
+
void fillCirclesRgb565Uniform(const std::uint16_t *xs, const std::uint16_t *ys, int count, int r, pixel::native_t color);
|
|
185
|
+
void fillCirclesRgb565WorldYSorted(const CircleEntry *circles, int count,
|
|
186
|
+
int r,
|
|
187
|
+
int yBandMinWorld, int yBandMaxWorld,
|
|
188
|
+
int xOffset, int yOffset);
|
|
189
|
+
void fillRoundedRectBoxesRgb565(const std::int16_t *xs, const std::int16_t *ys, int count,
|
|
190
|
+
int w, int h, int tl, int tr, int br, int bl,
|
|
191
|
+
const pixel::native_t *colors);
|
|
192
|
+
void strokeCircle(int cx, int cy, int r, pixel::native_t color);
|
|
193
|
+
void drawLine(int x0, int y0, int x1, int y1, pixel::native_t color);
|
|
194
|
+
void drawArc(int cx, int cy, int r, int start_deg, int end_deg, pixel::native_t color);
|
|
195
|
+
void fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2, pixel::native_t color);
|
|
196
|
+
void fillTriangleOpaque(int x0, int y0, int x1, int y1, int x2, int y2, pixel::native_t color);
|
|
197
|
+
// Opaque triangle BATCH with per-row span occlusion. Entries arrive
|
|
198
|
+
// farthest-first (painter's depth order); this walks them nearest-first and
|
|
199
|
+
// fills only pixels no nearer triangle has already covered — each pixel
|
|
200
|
+
// written once, occluded spans cost a coverage test instead of a fill. Same
|
|
201
|
+
// visible result as drawing the batch back-to-front with fillTriangleOpaque,
|
|
202
|
+
// but without the overdraw. Coords are world; ox/oy shift into this canvas's
|
|
203
|
+
// chunk-local space (like the fillTriangleOpaque caller does). Valid only for
|
|
204
|
+
// OPAQUE, depth-sorted batches. Coverage lives in per-core static scratch, so
|
|
205
|
+
// two Canvases on different cores may run this concurrently.
|
|
206
|
+
void fillTrianglesOpaqueOccluded(const TriangleEntry *tris, int count, int ox, int oy);
|
|
207
|
+
void drawText(const char *text, int x, int y, pixel::native_t color, float scale);
|
|
208
|
+
void drawTextFont(const char *text, int x, int y, pixel::native_t color, int font_id);
|
|
209
|
+
void drawTextFontFamily(const char *text, int x, int y, pixel::native_t color, int family_id, int size_px);
|
|
210
|
+
// Rotated 90deg for panel-native landscape rendering: the anchor and the
|
|
211
|
+
// text advance are in LANDSCAPE coordinates; every glyph pixel writes to
|
|
212
|
+
// the portrait panel address (panel_x = ly, panel_y = height-1-lx). The
|
|
213
|
+
// canvas must be bound to the FULL portrait buffer.
|
|
214
|
+
void drawTextFontFamilyRotated90(const char *text, int lx, int ly, pixel::native_t color, int family_id, int size_px);
|
|
215
|
+
void drawTextFontFamilyOnBackground(const char *text, int x, int y, pixel::native_t color,
|
|
216
|
+
int family_id, int size_px, pixel::native_t background);
|
|
217
|
+
int measureTextFontFamily(const char *text, int family_id, int size_px);
|
|
218
|
+
int measureTextInkCenterFontFamily(const char *text, int family_id, int size_px);
|
|
219
|
+
static void measureTextFont(const char *text, int max_width, int font_id, int *out_w, int *out_h);
|
|
220
|
+
void fillRoundedRect(int x, int y, int w, int h, int tl, int tr, int br, int bl, pixel::native_t color);
|
|
221
|
+
void strokeRoundedRect(int x, int y, int w, int h, int tl, int tr, int br, int bl, int lw, pixel::native_t color);
|
|
222
|
+
// Image sources are native_t (same format as the framebuffer for this
|
|
223
|
+
// target), so blits are a native copy/blend with no per-pixel conversion.
|
|
224
|
+
void drawImage(const pixel::native_t *src, const std::uint8_t *alpha, int src_w, int src_h, int dx, int dy);
|
|
225
|
+
#if GEA_PIXEL_STORAGE_PACKED
|
|
226
|
+
// Blit a packed source (a grayscale canvas surface, stored in the same
|
|
227
|
+
// sub-byte packing as the framebuffer) straight in — a direct same-depth
|
|
228
|
+
// copy, no unpack/repack. Clipped.
|
|
229
|
+
void blitPacked(const std::uint8_t *src, int src_w, int src_h, int dx, int dy);
|
|
230
|
+
#endif
|
|
231
|
+
void drawImage(const pixel::native_t *src, const std::uint8_t *alpha, int src_w, int src_h,
|
|
232
|
+
int dx, int dy, int dst_w, int dst_h);
|
|
233
|
+
void drawImageRotated90CW(const pixel::native_t *src, const std::uint8_t *alpha, int src_w, int src_h,
|
|
234
|
+
int dx, int dy, int dst_w, int dst_h);
|
|
235
|
+
void drawImageRounded(const pixel::native_t *src, const std::uint8_t *alpha, int src_w, int src_h,
|
|
236
|
+
int dx, int dy, int dst_w, int dst_h, int tl, int tr, int br, int bl);
|
|
237
|
+
void drawImageTiledX(const pixel::native_t *src, const std::uint8_t *alpha, int src_w, int src_h,
|
|
238
|
+
int dx, int dy, int width);
|
|
239
|
+
|
|
240
|
+
private:
|
|
241
|
+
void writePixel(int x, int y, pixel::native_t fg);
|
|
242
|
+
void writePixelAlpha(int x, int y, pixel::native_t fg, std::uint8_t alpha);
|
|
243
|
+
// Native-pixel writers: the colour is already this target's native pixel
|
|
244
|
+
// (e.g. an image source pixel), so there is no colour conversion — clip +
|
|
245
|
+
// global-alpha + dirty handling only. writePixel/writePixelAlpha are the
|
|
246
|
+
// RGB565-colour entry points and convert once via pixel::toNative().
|
|
247
|
+
void writePixelNative(int x, int y, pixel::native_t c);
|
|
248
|
+
void writePixelNativeAlpha(int x, int y, pixel::native_t c, std::uint8_t alpha);
|
|
249
|
+
// Fill `count` native pixels at physical row `phys` with an RGB565 colour
|
|
250
|
+
// (converted once to native). fillSpanGlobalAlpha honours globalAlpha_.
|
|
251
|
+
void fillSpanColor(int phys, int x0, int count, pixel::native_t color);
|
|
252
|
+
void fillSpanGlobalAlpha(int phys, int x0, int count, pixel::native_t color);
|
|
253
|
+
void markDirtyClipped(int x0, int y0, int x1, int y1);
|
|
254
|
+
void addDirtyRect(int x0, int y0, int x1, int y1);
|
|
255
|
+
bool fillCircleNoDirty(int cx, int cy, int r, pixel::native_t color);
|
|
256
|
+
void fillQuarterCircle(int cx, int cy, int r, int quadrant, pixel::native_t color);
|
|
257
|
+
void fillCircleBox(int x, int y, int size, pixel::native_t color);
|
|
258
|
+
void drawRasterizedText(const char *text, int x, int y, pixel::native_t color, const RasterizedFont &font);
|
|
259
|
+
// Blit a pre-rasterized glyph-coverage sprite (text-relative coords, origin at
|
|
260
|
+
// pen x/y, offset by minLX/minLY) honouring the current clip, global alpha and
|
|
261
|
+
// dirty accounting. Runs of fully-opaque coverage use the fast span fill.
|
|
262
|
+
// Used by the large-static-text sprite cache to avoid re-running the scattered
|
|
263
|
+
// flash-atlas glyph rasterizer every frame. cov is w*h coverage bytes; rowX0/
|
|
264
|
+
// rowX1 are per-row ink extents (rowX1 < rowX0 marks an empty row).
|
|
265
|
+
void blitGlyphSprite(const std::uint8_t *cov, const std::int16_t *rowX0, const std::int16_t *rowX1,
|
|
266
|
+
const std::uint8_t *rleVal, const std::uint16_t *rleLen, const std::int32_t *rleRowStart,
|
|
267
|
+
int minLX, int minLY, int w, int h, int x, int y, pixel::native_t color);
|
|
268
|
+
|
|
269
|
+
int width_ = 0;
|
|
270
|
+
int height_ = 0;
|
|
271
|
+
int stride_ = 0; // row stride in pixels (>= width_, may be padded)
|
|
272
|
+
int strideBytes_ = 0;
|
|
273
|
+
int regionY_ = 0; // scroll region origin row (logical)
|
|
274
|
+
int regionH_ = 0; // scroll region height; 0 = no region active
|
|
275
|
+
int scrollOffsetY_ = 0; // current rotation within region; see rowToPhysical()
|
|
276
|
+
pixel::native_t *pixels_ = nullptr;
|
|
277
|
+
|
|
278
|
+
int dirtyX0_ = 0;
|
|
279
|
+
int dirtyY0_ = 0;
|
|
280
|
+
int dirtyX1_ = -1;
|
|
281
|
+
int dirtyY1_ = -1;
|
|
282
|
+
CanvasDirtyRect dirtyRects_[kMaxDirtyRects] = {};
|
|
283
|
+
int dirtyRectCount_ = 0;
|
|
284
|
+
std::uint8_t globalAlpha_ = 255;
|
|
285
|
+
|
|
286
|
+
ClipRect clipStack_[kMaxClipDepth] = {};
|
|
287
|
+
int clipDepth_ = 0;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
} // namespace gea::framework::graphics
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "pixel.h"
|
|
4
|
+
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <cstddef>
|
|
7
|
+
|
|
8
|
+
namespace gea::framework::graphics {
|
|
9
|
+
struct CircleEntry; // canvas.h; only referenced by pointer here
|
|
10
|
+
struct TriangleEntry; // canvas.h; only referenced by pointer here
|
|
11
|
+
class Canvas;
|
|
12
|
+
} // namespace gea::framework::graphics
|
|
13
|
+
|
|
14
|
+
namespace gea::platform::display {
|
|
15
|
+
|
|
16
|
+
#ifndef GEA_EMBEDDED_DISPLAY_WIDTH
|
|
17
|
+
#define GEA_EMBEDDED_DISPLAY_WIDTH 410
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#ifndef GEA_EMBEDDED_DISPLAY_HEIGHT
|
|
21
|
+
#define GEA_EMBEDDED_DISPLAY_HEIGHT 502
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
#ifndef GEA_EMBEDDED_DISPLAY_NATIVE_WIDTH
|
|
25
|
+
#define GEA_EMBEDDED_DISPLAY_NATIVE_WIDTH GEA_EMBEDDED_DISPLAY_WIDTH
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#ifndef GEA_EMBEDDED_DISPLAY_NATIVE_HEIGHT
|
|
29
|
+
#define GEA_EMBEDDED_DISPLAY_NATIVE_HEIGHT GEA_EMBEDDED_DISPLAY_HEIGHT
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
inline constexpr int kWidth = GEA_EMBEDDED_DISPLAY_WIDTH;
|
|
33
|
+
inline constexpr int kHeight = GEA_EMBEDDED_DISPLAY_HEIGHT;
|
|
34
|
+
inline constexpr int kNativeWidth = GEA_EMBEDDED_DISPLAY_NATIVE_WIDTH;
|
|
35
|
+
inline constexpr int kNativeHeight = GEA_EMBEDDED_DISPLAY_NATIVE_HEIGHT;
|
|
36
|
+
inline constexpr int kConsoleFontWidth = 8;
|
|
37
|
+
inline constexpr int kConsoleFontHeight = 16;
|
|
38
|
+
inline constexpr int kConsoleFontScale = 3;
|
|
39
|
+
inline constexpr int kConsoleGlyphWidth = kConsoleFontWidth * kConsoleFontScale;
|
|
40
|
+
inline constexpr int kConsoleGlyphHeight = kConsoleFontHeight * kConsoleFontScale;
|
|
41
|
+
inline constexpr int kConsoleColumns = kWidth / kConsoleGlyphWidth;
|
|
42
|
+
inline constexpr int kConsoleRows = kHeight / kConsoleGlyphHeight;
|
|
43
|
+
|
|
44
|
+
struct DisplayFlushPerfStats {
|
|
45
|
+
int64_t totalUs = 0;
|
|
46
|
+
int64_t setWindowUs = 0;
|
|
47
|
+
int64_t slotWaitUs = 0;
|
|
48
|
+
int64_t copyUs = 0;
|
|
49
|
+
int64_t rasterUs = 0;
|
|
50
|
+
int64_t byteSwapUs = 0;
|
|
51
|
+
int64_t txUs = 0;
|
|
52
|
+
int64_t completeWaitUs = 0;
|
|
53
|
+
int64_t entryWaitUs = 0;
|
|
54
|
+
int64_t chunkWaitUs = 0;
|
|
55
|
+
int64_t tailWaitUs = 0;
|
|
56
|
+
int callCount = 0;
|
|
57
|
+
int chunkCount = 0;
|
|
58
|
+
int pixelCount = 0;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
struct DisplayFlushStageDetail {
|
|
62
|
+
int x0 = 0;
|
|
63
|
+
int y0 = 0;
|
|
64
|
+
int x1 = -1;
|
|
65
|
+
int y1 = -1;
|
|
66
|
+
int row = 0;
|
|
67
|
+
int rows = 0;
|
|
68
|
+
int pixels = 0;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
enum class DisplayPresentCommandType : uint8_t {
|
|
72
|
+
Clear,
|
|
73
|
+
FillRectRgb565,
|
|
74
|
+
StrokeRectRgb565,
|
|
75
|
+
FillTriangleRgb565,
|
|
76
|
+
FillCircleRgb565,
|
|
77
|
+
StrokeCircleRgb565,
|
|
78
|
+
FillCirclesRgb565,
|
|
79
|
+
DrawImage,
|
|
80
|
+
DrawImageScaled,
|
|
81
|
+
DrawImageRotated90CW,
|
|
82
|
+
DrawImageTiledX,
|
|
83
|
+
FillText,
|
|
84
|
+
FillTrianglesRgb565
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
struct DisplayPresentCommand {
|
|
88
|
+
DisplayPresentCommandType type = DisplayPresentCommandType::Clear;
|
|
89
|
+
union {
|
|
90
|
+
struct {
|
|
91
|
+
gea::framework::graphics::pixel::native_t color;
|
|
92
|
+
} clear;
|
|
93
|
+
struct {
|
|
94
|
+
int x;
|
|
95
|
+
int y;
|
|
96
|
+
int w;
|
|
97
|
+
int h;
|
|
98
|
+
gea::framework::graphics::pixel::native_t color;
|
|
99
|
+
uint8_t alpha;
|
|
100
|
+
} fillRectRgb565;
|
|
101
|
+
struct {
|
|
102
|
+
int x;
|
|
103
|
+
int y;
|
|
104
|
+
int w;
|
|
105
|
+
int h;
|
|
106
|
+
gea::framework::graphics::pixel::native_t color;
|
|
107
|
+
uint8_t alpha;
|
|
108
|
+
} strokeRectRgb565;
|
|
109
|
+
struct {
|
|
110
|
+
int x0;
|
|
111
|
+
int y0;
|
|
112
|
+
int x1;
|
|
113
|
+
int y1;
|
|
114
|
+
int x2;
|
|
115
|
+
int y2;
|
|
116
|
+
gea::framework::graphics::pixel::native_t color;
|
|
117
|
+
uint8_t alpha;
|
|
118
|
+
} fillTriangleRgb565;
|
|
119
|
+
struct {
|
|
120
|
+
int x;
|
|
121
|
+
int y;
|
|
122
|
+
int radius;
|
|
123
|
+
gea::framework::graphics::pixel::native_t color;
|
|
124
|
+
uint8_t alpha;
|
|
125
|
+
} fillCircleRgb565;
|
|
126
|
+
struct {
|
|
127
|
+
int x;
|
|
128
|
+
int y;
|
|
129
|
+
int radius;
|
|
130
|
+
gea::framework::graphics::pixel::native_t color;
|
|
131
|
+
uint8_t alpha;
|
|
132
|
+
} strokeCircleRgb565;
|
|
133
|
+
struct {
|
|
134
|
+
const uint16_t *xs;
|
|
135
|
+
const uint16_t *ys;
|
|
136
|
+
const gea::framework::graphics::pixel::native_t *colors;
|
|
137
|
+
int count;
|
|
138
|
+
int radius;
|
|
139
|
+
uint8_t alpha;
|
|
140
|
+
} fillCirclesRgb565;
|
|
141
|
+
struct {
|
|
142
|
+
// Entries pre-packed (and depth-ordered) by the canvas layer.
|
|
143
|
+
const gea::framework::graphics::TriangleEntry *entries;
|
|
144
|
+
int count;
|
|
145
|
+
uint8_t alpha;
|
|
146
|
+
} fillTrianglesRgb565;
|
|
147
|
+
struct {
|
|
148
|
+
const gea::framework::graphics::pixel::native_t *pixels;
|
|
149
|
+
const uint8_t *alphaPixels;
|
|
150
|
+
int srcWidth;
|
|
151
|
+
int srcHeight;
|
|
152
|
+
int x;
|
|
153
|
+
int y;
|
|
154
|
+
uint8_t alpha;
|
|
155
|
+
} drawImage;
|
|
156
|
+
struct {
|
|
157
|
+
const gea::framework::graphics::pixel::native_t *pixels;
|
|
158
|
+
const uint8_t *alphaPixels;
|
|
159
|
+
int srcWidth;
|
|
160
|
+
int srcHeight;
|
|
161
|
+
int x;
|
|
162
|
+
int y;
|
|
163
|
+
int w;
|
|
164
|
+
int h;
|
|
165
|
+
uint8_t alpha;
|
|
166
|
+
// Corner radius applied to the DESTINATION box, all four corners.
|
|
167
|
+
// min(w,h)/2 is a circle, which is how an opaque (alpha-free) sprite
|
|
168
|
+
// gets a round mask without carrying an alpha plane: the blit skips
|
|
169
|
+
// the outside-the-shape pixels instead of blending them.
|
|
170
|
+
int radius;
|
|
171
|
+
} drawImageScaled;
|
|
172
|
+
struct {
|
|
173
|
+
const gea::framework::graphics::pixel::native_t *pixels;
|
|
174
|
+
const uint8_t *alphaPixels;
|
|
175
|
+
int srcWidth;
|
|
176
|
+
int srcHeight;
|
|
177
|
+
int x;
|
|
178
|
+
int y;
|
|
179
|
+
int w;
|
|
180
|
+
int h;
|
|
181
|
+
uint8_t alpha;
|
|
182
|
+
} drawImageRotated90CW;
|
|
183
|
+
struct {
|
|
184
|
+
const gea::framework::graphics::pixel::native_t *pixels;
|
|
185
|
+
const uint8_t *alphaPixels;
|
|
186
|
+
int srcWidth;
|
|
187
|
+
int srcHeight;
|
|
188
|
+
int x;
|
|
189
|
+
int y;
|
|
190
|
+
int w;
|
|
191
|
+
uint8_t alpha;
|
|
192
|
+
} drawImageTiledX;
|
|
193
|
+
struct {
|
|
194
|
+
const char *text;
|
|
195
|
+
int x;
|
|
196
|
+
int y;
|
|
197
|
+
gea::framework::graphics::pixel::native_t color;
|
|
198
|
+
float scale;
|
|
199
|
+
int fontFamilyId;
|
|
200
|
+
int fontSizePx;
|
|
201
|
+
uint8_t alpha;
|
|
202
|
+
} fillText;
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Inclusive rect, half-open is fine if x1 < x0 (treated as empty by the
|
|
207
|
+
// driver). Used for multi-rect framebuffer flush.
|
|
208
|
+
struct DisplayFlushRect {
|
|
209
|
+
int x0;
|
|
210
|
+
int y0;
|
|
211
|
+
int x1;
|
|
212
|
+
int y1;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// The raster callback fills a NATIVE pixel row for a streamed region. This is
|
|
216
|
+
// native_t (identical to uint16_t on RGB565 targets — a no-op there); on a
|
|
217
|
+
// grayscale GRAY4/GRAY2 target it is the 1-byte gray value, so no RGB565 is
|
|
218
|
+
// dragged through the streaming path.
|
|
219
|
+
using DisplayStreamRasterFn = void (*)(gea::framework::graphics::pixel::native_t *pixels,
|
|
220
|
+
int width,
|
|
221
|
+
int height,
|
|
222
|
+
int origin_x,
|
|
223
|
+
int origin_y,
|
|
224
|
+
void *user);
|
|
225
|
+
|
|
226
|
+
class Display {
|
|
227
|
+
public:
|
|
228
|
+
static bool init();
|
|
229
|
+
static bool start();
|
|
230
|
+
static gea::framework::graphics::Canvas *canvas();
|
|
231
|
+
// True when canvas() is the panel's scanout framebuffer (no logical->panel
|
|
232
|
+
// rotation): writes to it appear on the next refresh with no flush/rotate.
|
|
233
|
+
// False when an orientation forces a separate logical framebuffer that must
|
|
234
|
+
// be PPA-rotated to the panel each flush. Defaults to false on targets that
|
|
235
|
+
// don't override it.
|
|
236
|
+
static bool framebufferIsPanelDirect();
|
|
237
|
+
// If the panel has a portrait scanout buffer a producer (e.g. the camera) can
|
|
238
|
+
// PPA/DMA straight into for a self-owned rect — no off-screen compose + re-blit —
|
|
239
|
+
// return it plus its width/height and true. False when the UI composes off-screen
|
|
240
|
+
// and a flush/rotate is required. Default false; only the DSI panel overrides it.
|
|
241
|
+
static bool panelScanoutSurface(uint16_t **out_buffer, int *out_width, int *out_height);
|
|
242
|
+
// One-pass camera→panel target. Given a logical rect (the viewfinder), returns the
|
|
243
|
+
// live panel scanout buffer + its pic dims, the panel rect that logical rect maps to
|
|
244
|
+
// under the current orientation, and the orientation's rotation in 90° steps (0..3).
|
|
245
|
+
// A producer (the camera) composes its own source rotation with out_rot_steps and
|
|
246
|
+
// scales+rotates straight into the panel in ONE PPA pass — no off-screen rotate-to-
|
|
247
|
+
// panel second pass. Available in any orientation. Default false on targets without it.
|
|
248
|
+
// out_flip is set to 1 when the producer covers the whole panel and a second
|
|
249
|
+
// framebuffer exists: out_buffer is then the non-scanned (back) buffer, and the
|
|
250
|
+
// producer must call flipPanelToBack() after writing it to swap it in tear-free at
|
|
251
|
+
// vblank. out_flip = 0 means out_buffer is the live scanned buffer (write in place).
|
|
252
|
+
static bool panelDirectTarget(int logical_x, int logical_y, int logical_w, int logical_h,
|
|
253
|
+
uint16_t **out_buffer, int *out_buffer_w, int *out_buffer_h,
|
|
254
|
+
int *out_panel_x, int *out_panel_y, int *out_panel_w, int *out_panel_h,
|
|
255
|
+
int *out_rot_steps, int *out_flip);
|
|
256
|
+
// Swap the back framebuffer (just written by a full-panel producer) in at the next
|
|
257
|
+
// vblank. No-op on single-framebuffer targets. The pointer overload flips the
|
|
258
|
+
// exact buffer returned by panelDirectTarget(); use it when a long producer could
|
|
259
|
+
// let the writable-buffer choice change before the flip.
|
|
260
|
+
static void flipPanelToBack();
|
|
261
|
+
static void flipPanelToBack(uint16_t *buffer);
|
|
262
|
+
static bool copySnapshotRgb565(uint16_t *dst, int pixel_capacity, int *width, int *height, bool presented);
|
|
263
|
+
// Same snapshot, but in the board's NATIVE sub-byte-PACKED storage (GRAY4/
|
|
264
|
+
// GRAY2 targets only -- GEA_PIXEL_STORAGE_PACKED) instead of expanded RGB565.
|
|
265
|
+
// A packed panel's true framebuffer is a quarter (GRAY4) or eighth (GRAY2)
|
|
266
|
+
// the size of an RGB565 expansion of the same pixels; a caller that needs
|
|
267
|
+
// RGB565 (the wire format screenshot commands emit) allocates this small
|
|
268
|
+
// buffer and expands per-pixel itself while it encodes, instead of asking
|
|
269
|
+
// the device to hold a full RGB565-sized allocation it may not have. `dst`
|
|
270
|
+
// is a flat, unpadded packed pixel STREAM: pixel index i (row-major,
|
|
271
|
+
// i = y*width+x) sits at pixel::packed::byteIndex(i)/shiftFor(i), with no
|
|
272
|
+
// per-row alignment gap -- so byte_capacity need only be
|
|
273
|
+
// pixel::packed::rowBytes(width*height). Only implemented on
|
|
274
|
+
// GEA_PIXEL_STORAGE_PACKED boards; RGB565/8888 targets never call it.
|
|
275
|
+
static bool copySnapshotPacked(uint8_t *dst, int byte_capacity, int *width, int *height, bool presented);
|
|
276
|
+
static int countNonBlackPixels(bool presented);
|
|
277
|
+
static void clear();
|
|
278
|
+
static void clearNoFlush();
|
|
279
|
+
static void print(const char *text);
|
|
280
|
+
static void flush();
|
|
281
|
+
// Transmit `count` framebuffer rects to the panel inside one driver
|
|
282
|
+
// entry. Each rect is independently chunked / windowed (we can't merge
|
|
283
|
+
// without re-transmitting between rects), but we share the call boundary
|
|
284
|
+
// so callers that already track multiple dirty rects (tree_render's
|
|
285
|
+
// per-region replay loop) don't pay 16× the per-call overhead. After a
|
|
286
|
+
// successful return the canvas dirty rect is cleared; passing rects
|
|
287
|
+
// outside the framebuffer is silently clipped.
|
|
288
|
+
static void flushRects(const DisplayFlushRect *rects, int count, bool allowPerChunkDrain = true);
|
|
289
|
+
// Fused flush: instead of copying each window from the framebuffer, invoke `raster`
|
|
290
|
+
// to generate each DMA chunk in place (the render layer rebinds the draw canvas onto
|
|
291
|
+
// the chunk buffer and replays the dirty display-list into it). Skips the PSRAM
|
|
292
|
+
// framebuffer round-trip and overlaps rasterization with DMA. Call
|
|
293
|
+
// rebindCanvasToFramebuffer() afterward to restore the canvas binding.
|
|
294
|
+
static void flushRectsRasterized(const DisplayFlushRect *rects, int count, DisplayStreamRasterFn raster, void *user, bool allowPerChunkDrain = true);
|
|
295
|
+
static void rebindCanvasToFramebuffer();
|
|
296
|
+
static bool streamRect(int x, int y, int w, int h, DisplayStreamRasterFn raster, void *user);
|
|
297
|
+
static bool present(const DisplayPresentCommand *commands, int command_count);
|
|
298
|
+
static void setFlushConfig(int chunk_rows, int queue_depth);
|
|
299
|
+
// Present render scale: 1 = native, 2 = the app renders into a half-panel
|
|
300
|
+
// viewport and present() 2x-upscales it to the panel (quarters fill/overdraw).
|
|
301
|
+
// Per-present, so it never affects full-res apps sharing the present path.
|
|
302
|
+
// Only the ESP32 backend implements the upscale; other targets no-op.
|
|
303
|
+
static void setPresentScale(int scale);
|
|
304
|
+
// Reserve `bytes` of internal RAM by shrinking the elastic staging budget
|
|
305
|
+
// (release with reserveInternal(0)). Used by the connectivity layer so WiFi/
|
|
306
|
+
// BLE bring-up has headroom; the staging resize is applied on the frame task.
|
|
307
|
+
static void reserveInternal(std::size_t bytes);
|
|
308
|
+
// Apply a pending reserveInternal() staging resize. Call once per frame on the
|
|
309
|
+
// frame task: the resize otherwise only lands inside a content flush, so a
|
|
310
|
+
// static screen (no dirty region to flush) would never free the reserved RAM.
|
|
311
|
+
static void applyPendingInternalReserve();
|
|
312
|
+
static int flushChunkRows();
|
|
313
|
+
static int flushQueueDepth();
|
|
314
|
+
static int flushBufferBytes();
|
|
315
|
+
static void pushClip(int x, int y, int w, int h);
|
|
316
|
+
static void popClip();
|
|
317
|
+
static void resetClip();
|
|
318
|
+
static void setAlpha(uint8_t alpha);
|
|
319
|
+
static uint8_t alpha();
|
|
320
|
+
static void setAA(int samples);
|
|
321
|
+
static int aa();
|
|
322
|
+
static int brightness();
|
|
323
|
+
static void setBrightness(int brightness_percent);
|
|
324
|
+
// High-brightness mode: a separate, higher ceiling than the 0-100 brightness
|
|
325
|
+
// range (a sunlight boost on AMOLED controllers that have one). Deliberately
|
|
326
|
+
// a toggle, not brightness > 100, so a slider can never reach it. Returns
|
|
327
|
+
// false where the panel has no such mode.
|
|
328
|
+
static bool setHighBrightnessMode(bool enabled);
|
|
329
|
+
static bool highBrightnessMode();
|
|
330
|
+
// Opt-in tearing sync (TE/VBlank). Off by default. When enabled, the frame
|
|
331
|
+
// scheduler calls vsyncWaitForFrame() at the top of each frame so the app's
|
|
332
|
+
// draw+flush lands inside the panel's VBlank lead window. No-op on targets
|
|
333
|
+
// that don't wire a TE line. Toggled from TS via Display.setVSync(boolean).
|
|
334
|
+
static void setVSync(bool on);
|
|
335
|
+
static bool vsyncEnabled();
|
|
336
|
+
// Mark the next present as a full-screen damage-all: skip the dirty-rect diff
|
|
337
|
+
// and the persistent previous-frame copy for that frame. Toggled from TS via
|
|
338
|
+
// Display.invalidate() while panning. No-op on targets without a present diff.
|
|
339
|
+
static void invalidate();
|
|
340
|
+
static void vsyncWaitForFrame();
|
|
341
|
+
static void clip(int *x0, int *y0, int *x1, int *y1);
|
|
342
|
+
static void fillRect(int x, int y, int w, int h, gea::framework::graphics::pixel::native_t color);
|
|
343
|
+
static void scrollRect(int x, int y, int w, int h, int dx, int dy);
|
|
344
|
+
// Drop any active software-scroll-register state. Called by Tree::clear()
|
|
345
|
+
// when the tree is torn down (app switch / mount of a fresh tree) so the
|
|
346
|
+
// next app's drawing isn't translated through the previous app's region.
|
|
347
|
+
// No-op on platforms / native-test stubs that don't implement the
|
|
348
|
+
// software scroll register.
|
|
349
|
+
static void resetScrollRegion();
|
|
350
|
+
static void strokeRect(int x, int y, int w, int h, gea::framework::graphics::pixel::native_t color);
|
|
351
|
+
static void fillCircle(int cx, int cy, int r, gea::framework::graphics::pixel::native_t color);
|
|
352
|
+
static void strokeCircle(int cx, int cy, int r, gea::framework::graphics::pixel::native_t color);
|
|
353
|
+
static void drawLine(int x0, int y0, int x1, int y1, gea::framework::graphics::pixel::native_t color);
|
|
354
|
+
static void drawArc(int cx, int cy, int r, int start_deg, int end_deg, gea::framework::graphics::pixel::native_t color);
|
|
355
|
+
static void fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2, gea::framework::graphics::pixel::native_t color);
|
|
356
|
+
static void drawText(const char *text, int x, int y, gea::framework::graphics::pixel::native_t color, float scale);
|
|
357
|
+
static void drawTextFont(const char *text, int x, int y, gea::framework::graphics::pixel::native_t color, int font_id);
|
|
358
|
+
static void drawTextFontFamily(const char *text, int x, int y, gea::framework::graphics::pixel::native_t color, int family_id, int size_px);
|
|
359
|
+
static void setPixel(int x, int y, gea::framework::graphics::pixel::native_t color);
|
|
360
|
+
static void fillRoundedRect(int x, int y, int w, int h, int tl, int tr, int br, int bl, gea::framework::graphics::pixel::native_t color);
|
|
361
|
+
static void fillRoundedRectBoxesRgb565(const int16_t *xs, const int16_t *ys, int count,
|
|
362
|
+
int w, int h, int tl, int tr, int br, int bl,
|
|
363
|
+
const gea::framework::graphics::pixel::native_t *colors);
|
|
364
|
+
static void strokeRoundedRect(int x, int y, int w, int h, int tl, int tr, int br, int bl, int lw, gea::framework::graphics::pixel::native_t color);
|
|
365
|
+
static void blitImage(const gea::framework::graphics::pixel::native_t *src, const uint8_t *alpha, int src_w, int src_h, int dx, int dy);
|
|
366
|
+
static void blitImageScaled(const gea::framework::graphics::pixel::native_t *src, const uint8_t *alpha, int src_w, int src_h, int dx, int dy, int dst_w, int dst_h);
|
|
367
|
+
static void setWorldOverlay(const uint16_t *world_pixels, int world_width, int world_height, int panel_top, int panel_height);
|
|
368
|
+
static void setWorldScroll(int scroll_x);
|
|
369
|
+
static void flushStatsRead(int64_t *total_us, int *call_count, int *pixel_count);
|
|
370
|
+
static DisplayFlushPerfStats flushPerfStatsRead();
|
|
371
|
+
// Cumulative flush odometer, never reset per frame -- lets a caller watch for
|
|
372
|
+
// the panel going quiet after an interaction (flushPerfStatsRead is zeroed
|
|
373
|
+
// every frame, so it cannot answer that).
|
|
374
|
+
static void flushOdometerRead(uint32_t &calls, uint64_t &pixels);
|
|
375
|
+
// Present-path diagnostics for GEADEV (counters + last tile-shape
|
|
376
|
+
// ineligibility); boards without a batched present leave outputs zero.
|
|
377
|
+
static void presentPathDebug(int *calls, int *direct, int *general, int *rejected,
|
|
378
|
+
int *tileShapeFailKind, int *tileShapeFailType, int *tileShapeFailCount);
|
|
379
|
+
static void landFrameDebug(int *total, int *align, int *raster, int *text, int *flip);
|
|
380
|
+
static void landPanDebug(int *detect, int *kick, int *strips, int *wait, int *interior);
|
|
381
|
+
static void flushStatsReset();
|
|
382
|
+
// Diagnostic: name of the current display flush sub-stage, plus the chunk
|
|
383
|
+
// or region index in flight. Returned name is a static string. Safe to
|
|
384
|
+
// call from any task (atomic load).
|
|
385
|
+
static const char *flushStageName();
|
|
386
|
+
static int flushStageChunk();
|
|
387
|
+
static DisplayFlushStageDetail flushStageDetail();
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
} // namespace gea::platform::display
|