Adding Rounded Corners to Obelix/Core Time 2 Compositor

The first thing I noticed about my early alpha Core Time 2 unit is that the rounded bezel floats slightly above the display, and if the watch is viewed at an angle, the sharp corners of the display panel are immediately visible. I found this very jarring and distracting.

I see the way that silk and asterix draw their rounded corners to the display without affecting the system framebuffer, at lines 20 and 34 of compositor_display.c. I’m going to try and add a new rounded corner shape definition for obelix, to visually correct for the difference between the panel and the bezel.

2 Likes

I started out by measuring the corner radius of my watch with calipers, and found the radius to be around 2mm. Through copious use of online PPI calculators, i found that for a display 200px wide, 228px tall, and at 202PPI, a radius of 2mm worked out to about ~16px.

I created a simple test image, of a rectangle the size of obelix’s display, with 16px radius corners, and red outside of those corners. I used @hellcp ‘s bitmap-gallery to easily display the image on the watch screen, and found that I could not see the red pixels from straight ahead, but they were revealed as I tilted the watch. Awesome! That meant that 16px radius was a reasonable number to cut off the digital corners.

Working in Aseprite to narrow down the shape in 1bit pixels, I arrived at this shape:

1 Like
Here's the diff!
index 320737c5..96606401 100644
--- a/src/fw/services/common/compositor/compositor_display.c
+++ b/src/fw/services/common/compositor/compositor_display.c
@@ -22,6 +22,11 @@ static const uint8_t s_corner_shape[] = { 3, 1, 1 };
 static uint8_t s_line_buffer[FRAMEBUFFER_BYTES_PER_ROW];
 #endif

+#if PLATFORM_OBELIX
+static const uint8_t s_corner_shape[] = { 12, 9, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1 };
+static uint8_t s_line_buffer[FRAMEBUFFER_BYTES_PER_ROW];
+#endif
+
 //! display_update get next line callback
 static bool prv_flush_get_next_line_cb(DisplayRow* row) {
   FrameBuffer *fb = compositor_get_framebuffer();
@@ -31,7 +36,7 @@ static bool prv_flush_get_next_line_cb(DisplayRow* row) {
   if (s_current_flush_line < y_end) {
     row->address = s_current_flush_line;
     void *fb_line = framebuffer_get_line(fb, s_current_flush_line);
-#if PLATFORM_SILK || PLATFORM_ASTERIX
+#if PLATFORM_SILK || PLATFORM_ASTERIX || PLATFORM_OBELIX
     // Draw rounded corners onto the screen without modifying the
     // system framebuffer.
     if (s_current_flush_line < ARRAY_LENGTH(s_corner_shape) ||```

okay, i have written the code, and now to test it, i have to get my computer building the rest of the fucking pebble-firmware; please stand by

2 Likes

Did you test it with larger radii? I would love to see that!

1 Like

Sure - here are four different radii in the picker

14px


16px


"20px


"24px


The whole procedure has me doubting myself and the screen alignment on my unit. Wish I still had a backlight. (Or a desk lamp handy!)

1 Like

Oh wow, yeah, the screen alignment looks a little rough! 16px looks perfect though at least for most corners. Also lol at Leco’s X character, that’s proper wonky looking!

1 Like

Here’s how that first try went:


I’m wondering if FRAMEBUFFER_BYTES_PER_ROW is not present or not correct on obelix. i’m going to try the same corner shape on my asterix to see if that makes a difference.

1 Like


The corner shapes work! But they don’t work on my obelix. Hmm. I don’t really understand the specifics of the framebuffer and data strucutres for what’s going on here, but I can probably dig into the way the artificial bezel works for apps in compatibility mode for some clues.

Also, it occurs to me that the corner shapes here don’t have to be an even, circular radius! You could get fancy if you wanted, and have the entire system display in a shape like this one:

1 Like

I think the problem here is that I have a block of 1bit framebuffer manipulation, only expected to ever run on silk and asterix, and I’m suddenly enabling it for a platform with a whole byte per pixel, and a lot more pixels. The equivalent of this for color systems ran on snowy’s FPGA gateware, not in the OS compositor, so I’m not able to reference that implementation.

The bluetooth fails on these firmware builds, and the display doesn’t shimmer when i press the buttons, which tells me more things are going wrong than just the pixels being misaligned. Maybe I’m blowing up the size of a buffer somewhere. My compsci background is pretty simplistic and sparse, and I’m having a lot of trouble understanding what I’m looking at when it comes to the math and logic of the function itself, so unfortunately this is as far as I can go. If anyone is interested in picking this effort up, my commit lives here: compositor_display: Draw round display corners on Obelix · lavglaab/PebbleOS@44770ab · GitHub

1 Like

Found what’s wrong, and it might be a tricky one to fix.

Since this change: drivers/sf32lb52: Eliminate redundant display framebuffer to save 44KB · coredevices/PebbleOS@65d6e15 · GitHub , the Obelix display driver reuses the compositor framebuffer, saving the address returned by the first prv_flush_get_next_line_cb call. It converts the pixel format from RGB222 to RGB332 in-place, sends it to the SF32LB52’s display controller in one go, then converts back to RGB222.

The problem is that the corner rendering code is designed to process one line at a time, reusing s_line_buffer for every line that includes part of the corners. Now, the Obelix display driver will try to read and write 228 lines from s_line_buffer, corrupting something like 45KB.

I don’t know if there’s a good way to fix this without bringing back the redundant framebuffer :confused: . Maybe if there’s no other plans to use the SF32LB52’s second graphics layer, that layer could be filled with a corner overlay at start-up? It would mean that layer can’t be used for other things, so it would be worth discussing with Core devs first.

2 Likes

Nod. @jplexer if you have any time spare, could you take a look at this with me?

1 Like

oh yeah 100%!

also my message needs to be longer apparently

1 Like

@lavender compositor_display: Draw round display corners on Obelix by jplexer · Pull Request #594 · coredevices/PebbleOS · GitHub

2 Likes

For posterity, I did check the screen alignment some more, and I don’t think the panel alignment is actually a problem, I think it just looks bad because of the floating bezel and shadow obscuring the edges of the panel at slight angles. Here is what my display looks like in PRF hardware verification:

Three photos



1 Like