Skip to content

Commit d59d42b

Browse files
author
cbicco888
committed
Applying copilot reviewed changes
1 parent e477770 commit d59d42b

7 files changed

Lines changed: 193 additions & 82 deletions

File tree

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1 @@
1-
# Contributing
2-
3-
Thanks for contributing.
4-
5-
## Sign-off / DCO
6-
7-
All changes should include a Signed-off-by line in each commit message, certifying you have the right to submit the work under the project license.
8-
9-
## Submitting changes
10-
11-
- Keep changes focused and easy to review.
12-
- Run a local build before posting a PR.
13-
- Include a clear description of what changed and why.
14-
15-
## License
16-
17-
By contributing, you agree that your contributions will be licensed under the Apache License, Version 2.0 (see `LICENSE`).
18-
1+
If you would like to contribute code to this project you can do so through GitHub by forking the repository and sending a pull request. Before RDK accepts your code into the project you must sign the RDK Contributor License Agreement (CLA).

rdke_splash_opengles/COPYING

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
This project is licensed under the Apache License, Version 2.0.
2-
3-
See the LICENSE file in this directory.
1+
LICENSE

rdke_splash_opengles/LICENSE

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
source, and configuration files.
2929

3030
"Object" form shall mean any form resulting from mechanical
31-
transformation or translation of a Source form, including but not
32-
limited to compiled object code, generated documentation,
31+
transformation or translation of a Source form, including but
32+
not limited to compiled object code, generated documentation,
3333
and conversions to other media types.
3434

3535
"Work" shall mean the work of authorship, whether in Source or
@@ -199,3 +199,25 @@
199199
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200200
See the License for the specific language governing permissions and
201201
limitations under the License.
202+
203+
204+
MIT License
205+
===========
206+
Permission is hereby granted, free of charge, to any person obtaining a
207+
copy of this software and associated documentation files (the "Software"),
208+
to deal in the Software without restriction, including without limitation
209+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
210+
and/or sell copies of the Software, and to permit persons to whom the
211+
Software is furnished to do so, subject to the following conditions:
212+
213+
The above copyright notice and this permission notice (including the next
214+
paragraph) shall be included in all copies or substantial portions of the
215+
Software.
216+
217+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
218+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
219+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
220+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
221+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
222+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
223+
DEALINGS IN THE SOFTWARE.

rdke_splash_opengles/NOTICE

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,45 @@
1-
RDK Splash Screen (rdke_splash_opengles)
2-
Copyright 2026 RDK Management
1+
This component contains software that is Copyright (c) 2026 RDK Management.
2+
The component is licensed to you under the Apache License, Version 2.0 (the "License").
3+
You may not use the component except in compliance with the License.
34

4-
This product includes software developed as part of the RDK project.
5+
The component may include material which is licensed under other licenses / copyrights as
6+
listed below. Your use of this material within the component is also subject to the terms and
7+
conditions of these licenses. The LICENSE file contains the text of all the licenses which apply
8+
within this component, except as indicated in the following paragraph.
59

6-
The rdke_splash_opengles source code is licensed under the Apache License, Version 2.0.
7-
See the LICENSE file for details.
810

11+
Copyright © 2008-2013 Kristian Høgsberg
12+
Copyright © 2013 Rafael Antognolli
13+
Copyright © 2013 Jasper St. Pierre
14+
Copyright © 2010-2013 Intel Corporation
15+
Licensed under the MIT License
16+
17+
Copyright © 2010 Intel Corporation
18+
Copyright © 2011 Benjamin Franzke
19+
Copyright © 2012-2013 Collabora, Ltd.
20+
Licensed under the MIT License
21+
22+
Copyright © 2011 Kristian Høgsberg
23+
Copyright © 2011 Benjamin Franzke
24+
Licensed under the MIT License
25+
26+
Copyright © 2008-2011 Kristian Høgsberg
27+
Copyright © 2010-2011 Intel Corporation
28+
Licensed under the MIT License
29+
30+
Copyright (c) 2007-2009 The Khronos Group Inc.
31+
Licensed under the MIT License
32+
33+
Copyright (c) 2007-2013 The Khronos Group Inc.
34+
Licensed under the MIT License
35+
36+
Copyright (c) 2013 The Khronos Group Inc.
37+
Licensed under the MIT License
38+
39+
Copyright © 2014,2015,2018 Collabora, Ltd.
40+
Licensed under the MIT License
41+
42+
Copyright 2016 The Chromium Authors.
43+
Copyright 2017 Intel Corporation
44+
Copyright 2018 Collabora, Ltd
45+
Licensed under the MIT License

rdke_splash_opengles/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,7 @@ Notes:
6868
### Exit codes
6969

7070
- `0`: normal exit (dismiss file detected)
71-
- `1`: usage/config/runtime failure (e.g., GL init failure)
71+
- `1`: usage, configuration, or other generic runtime failure (including invalid/unknown CLI arguments)
72+
- `2`: unused/reserved
73+
- `3`: `EssContextCreate` failed
74+
- `4`: startup failed

rdke_splash_opengles/rdke_splash.service

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
[Unit]
2121
Description=RDK Splash Screen
2222
After=log-rdk-start.service
23+
StartLimitIntervalSec=30
24+
StartLimitBurst=5
2325

2426
[Service]
2527
Type=simple
@@ -29,6 +31,7 @@ Environment="LD_PRELOAD=libwesteros_gl.so.0.0.0"
2931
# If no --image is provided, the app shows an internal fallback splash.
3032
ExecStart=/usr/bin/rdke_splash
3133
Restart=on-failure
34+
RestartSec=2
3235

3336
[Install]
3437
WantedBy=multi-user.target

rdke_splash_opengles/src/main.cpp

Lines changed: 118 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ namespace
5555
{
5656
constexpr const char* kDefaultDismissFile = "/tmp/.dismissSplash";
5757

58+
// The splash is static: redraw only when needed (first frame, display-size change).
59+
// Poll the dismiss file on a short timer to remain responsive without busy-spinning.
60+
constexpr uint64_t kDismissPollIntervalMs = 50;
61+
62+
// Some platforms/compositors expect periodic presents; redraw/present at ~20Hz to
63+
// avoid flicker while keeping CPU/GPU usage low.
64+
constexpr uint64_t kRedrawIntervalMs = 50;
65+
66+
// Pump the Essos event loop more frequently than we redraw to keep IPC/input
67+
// latency low (e.g. compositor/display messages).
68+
constexpr useconds_t kEventLoopSleepUs = 10'000;
69+
5870
volatile std::sig_atomic_t gShouldQuit = 0;
5971

6072
uint64_t nowMs()
@@ -156,19 +168,17 @@ std::optional<Image> decodeJpegToRgba(const std::string& path)
156168
const int y = static_cast<int>(cinfo.output_scanline - 1);
157169
uint8_t* dst = out.rgba.data() + (static_cast<size_t>(y) * static_cast<size_t>(width) * 4);
158170

159-
if (components == 3)
171+
for (int x = 0; x < width; ++x)
160172
{
161-
for (int x = 0; x < width; ++x)
162-
{
163-
const uint8_t r = row[static_cast<size_t>(x) * 3 + 0];
164-
const uint8_t g = row[static_cast<size_t>(x) * 3 + 1];
165-
const uint8_t b = row[static_cast<size_t>(x) * 3 + 2];
166-
dst[static_cast<size_t>(x) * 4 + 0] = r;
167-
dst[static_cast<size_t>(x) * 4 + 1] = g;
168-
dst[static_cast<size_t>(x) * 4 + 2] = b;
169-
dst[static_cast<size_t>(x) * 4 + 3] = 0xFF;
170-
}
173+
const uint8_t r = row[static_cast<size_t>(x) * 3 + 0];
174+
const uint8_t g = row[static_cast<size_t>(x) * 3 + 1];
175+
const uint8_t b = row[static_cast<size_t>(x) * 3 + 2];
176+
dst[static_cast<size_t>(x) * 4 + 0] = r;
177+
dst[static_cast<size_t>(x) * 4 + 1] = g;
178+
dst[static_cast<size_t>(x) * 4 + 2] = b;
179+
dst[static_cast<size_t>(x) * 4 + 3] = 0xFF;
171180
}
181+
172182
}
173183

174184
jpeg_finish_decompress(&cinfo);
@@ -243,6 +253,9 @@ std::optional<Image> decodePngToRgba(const std::string& path)
243253
int colorType = 0;
244254
png_get_IHDR(pngPtr, infoPtr, &width, &height, &bitDepth, &colorType, nullptr, nullptr, nullptr);
245255

256+
const bool fileHasAlpha = (colorType & PNG_COLOR_MASK_ALPHA) != 0;
257+
const bool fileHasTrns = png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS) != 0;
258+
246259
if (bitDepth == 16)
247260
png_set_strip_16(pngPtr);
248261

@@ -252,18 +265,32 @@ std::optional<Image> decodePngToRgba(const std::string& path)
252265
if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
253266
png_set_expand_gray_1_2_4_to_8(pngPtr);
254267

255-
if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
268+
if (fileHasTrns)
256269
png_set_tRNS_to_alpha(pngPtr);
257270

258271
if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
259272
png_set_gray_to_rgb(pngPtr);
260273

261-
// Ensure RGBA.
262-
if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_PALETTE)
274+
// Ensure RGBA output. After our transforms, the output will have an alpha
275+
// channel iff the file already had one OR we expanded tRNS.
276+
const bool outputHasAlpha = fileHasAlpha || fileHasTrns;
277+
if (!outputHasAlpha)
263278
png_set_filler(pngPtr, 0xFF, PNG_FILLER_AFTER);
264279

265280
png_read_update_info(pngPtr, infoPtr);
266281

282+
// Re-query post-transform state for clarity/robustness.
283+
const int outColorType = png_get_color_type(pngPtr, infoPtr);
284+
const int outBitDepth = png_get_bit_depth(pngPtr, infoPtr);
285+
if (outColorType != PNG_COLOR_TYPE_RGBA || outBitDepth != 8)
286+
{
287+
std::printf("decodePng: unsupported output format after transforms: colorType=%d bitDepth=%d\n",
288+
outColorType, outBitDepth);
289+
png_destroy_read_struct(&pngPtr, &infoPtr, nullptr);
290+
std::fclose(fp);
291+
return std::nullopt;
292+
}
293+
267294
const png_size_t rowBytes = png_get_rowbytes(pngPtr, infoPtr);
268295
if (rowBytes != width * 4)
269296
{
@@ -694,60 +721,98 @@ int main(int argc, char** argv)
694721
glEnableVertexAttribArray(1);
695722

696723
bool firstFrame = true;
724+
bool warnedNoDisplaySize = false;
725+
int lastDrawDisplayWidth = -1;
726+
int lastDrawDisplayHeight = -1;
727+
uint64_t lastDrawMs = 0;
728+
uint64_t lastDismissCheckMs = 0;
697729
while (!gShouldQuit)
698730
{
699-
if (fileExists(opt->dismissFile.c_str()))
700-
break;
731+
const uint64_t loopNowMs = nowMs();
732+
if (lastDismissCheckMs == 0 || (loopNowMs - lastDismissCheckMs) >= kDismissPollIntervalMs)
733+
{
734+
lastDismissCheckMs = loopNowMs;
735+
if (fileExists(opt->dismissFile.c_str()))
736+
break;
737+
}
701738

702-
// Preserve aspect ratio by fitting the image into the display with
703-
// letterboxing/pillarboxing.
704-
GLfloat scaleX = 1.0f;
705-
GLfloat scaleY = 1.0f;
706-
if (display.width > 0 && display.height > 0 && image->width > 0 && image->height > 0)
739+
if (display.width <= 0 || display.height <= 0)
707740
{
708-
const double displayAspect = static_cast<double>(display.width) / static_cast<double>(display.height);
709-
const double imageAspect = static_cast<double>(image->width) / static_cast<double>(image->height);
710-
if (imageAspect > displayAspect)
741+
if (!warnedNoDisplaySize)
711742
{
712-
scaleY = static_cast<GLfloat>(displayAspect / imageAspect);
743+
warnedNoDisplaySize = true;
744+
std::printf("Display size not available yet (got %dx%d); waiting for settings update...\n",
745+
display.width, display.height);
713746
}
714-
else
747+
748+
EssContextRunEventLoopOnce(ctx);
749+
usleep(kEventLoopSleepUs);
750+
continue;
751+
}
752+
753+
const bool displayChanged = (display.width != lastDrawDisplayWidth) || (display.height != lastDrawDisplayHeight);
754+
const bool dueToRedraw = (lastDrawMs == 0) || ((loopNowMs - lastDrawMs) >= kRedrawIntervalMs);
755+
const bool shouldDraw = firstFrame || displayChanged || dueToRedraw;
756+
757+
if (shouldDraw)
758+
{
759+
// Re-assert key GL state before drawing in case the platform touches it.
760+
glUseProgram(gl.program);
761+
glActiveTexture(GL_TEXTURE0);
762+
glBindTexture(GL_TEXTURE_2D, gl.texture);
763+
764+
// Preserve aspect ratio by fitting the image into the display with
765+
// letterboxing/pillarboxing.
766+
GLfloat scaleX = 1.0f;
767+
GLfloat scaleY = 1.0f;
768+
if (display.width > 0 && display.height > 0 && image->width > 0 && image->height > 0)
715769
{
716-
scaleX = static_cast<GLfloat>(imageAspect / displayAspect);
770+
const double displayAspect = static_cast<double>(display.width) / static_cast<double>(display.height);
771+
const double imageAspect = static_cast<double>(image->width) / static_cast<double>(image->height);
772+
if (imageAspect > displayAspect)
773+
{
774+
scaleY = static_cast<GLfloat>(displayAspect / imageAspect);
775+
}
776+
else
777+
{
778+
scaleX = static_cast<GLfloat>(imageAspect / displayAspect);
779+
}
717780
}
718-
}
719781

720-
const GLfloat verts[4][2] = {
721-
{-scaleX, -scaleY},
722-
{scaleX, -scaleY},
723-
{-scaleX, scaleY},
724-
{scaleX, scaleY},
725-
};
782+
const GLfloat verts[4][2] = {
783+
{-scaleX, -scaleY},
784+
{scaleX, -scaleY},
785+
{-scaleX, scaleY},
786+
{scaleX, scaleY},
787+
};
726788

727-
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
789+
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
728790

729-
glViewport(0, 0, display.width, display.height);
730-
glClear(GL_COLOR_BUFFER_BIT);
731-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
791+
glViewport(0, 0, display.width, display.height);
792+
glClear(GL_COLOR_BUFFER_BIT);
793+
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
732794

733-
if (firstFrame)
734-
{
735-
firstFrame = false;
736-
char msg[256];
737-
std::snprintf(msg, sizeof(msg),
738-
"RDKE_Splash first_frame_ms=%llu decode_ms=%llu gl_setup_ms=%llu img=%dx%d",
739-
static_cast<unsigned long long>(nowMs() - startMs),
740-
static_cast<unsigned long long>(decodeMs),
741-
static_cast<unsigned long long>(glSetupMs),
742-
image->width, image->height);
743-
std::printf("%s\n", msg);
795+
// Present only after drawing a frame.
796+
EssContextUpdateDisplay(ctx);
797+
glFlush();
798+
799+
lastDrawMs = loopNowMs;
800+
lastDrawDisplayWidth = display.width;
801+
lastDrawDisplayHeight = display.height;
802+
803+
if (firstFrame)
804+
{
805+
firstFrame = false;
806+
std::printf("RDKE_Splash first_frame_ms=%llu decode_ms=%llu gl_setup_ms=%llu img=%dx%d\n",
807+
static_cast<unsigned long long>(nowMs() - startMs),
808+
static_cast<unsigned long long>(decodeMs),
809+
static_cast<unsigned long long>(glSetupMs),
810+
image->width, image->height);
811+
}
744812
}
745813

746-
EssContextUpdateDisplay(ctx);
747814
EssContextRunEventLoopOnce(ctx);
748-
749-
// Reduce CPU/GPU usage while the splash is static.
750-
usleep(50 * 1000);
815+
usleep(kEventLoopSleepUs);
751816
}
752817

753818
destroyProgramAndTexture(gl);

0 commit comments

Comments
 (0)