[Samsung Gear 2] biktor_gj:
For everyone who's not understanding what happens with all this (there'll be some accuracy issues to keep it simple):

A framebuffer is a memory region used to draw the images that show up on the screen.

The kernel driver (s3c-fb) makes 5 different framebuffers to allocate images. It defaults one of them and whatever is written to it gets shown on the screen (in most exynos it's fb3. On previous versions of the graphic libraries, you could see, in /dev/, something like this:

/dev/graphics/fb0

/dev/graphics/fb1

/dev/graphics/fb2

/dev/graphics/fb3

/dev/graphics/fb4

/dev/graphics/fb5 <-- if you had a camera

In Mali Release 4, you only have 1 framebuffer device, but still have 5 "windows" (it's what it calls them). They work the same but without the need of having 5 separate devices in the device folder, and the driver can switch between them as they need. You can write an image to a framebuffer which is not being showed, and when the frame is ready, you switch to it to display it on the screen. That way you don't see glitches or garbage on screen as a result of redrawing the image (among a lot of other things).

Now, Android does more things with this. The hardware composer is used to switch between framebuffers, but also to use GPU's hardware acceleration to compose frames. In the case of the clocks, what it does, more or less, is:

Creates an empty framebuffer to allocate the data (with the help of Graphics Allocator -gralloc- which is used to handle framebuffer memory)

I/DisplayManagerService( 415): Display device added: DisplayDeviceInfo{"ActivityViewVirtualDisplay": 320 x 320, 60.0 fps, density 240, 240.0 x 240.0 dpi, touch NONE, rotation 0, type VIRTUAL, state OFF, owner android (uid 1000), FLAG_OWN_CONTENT_ONLY}

Sends data to the GPU to process the OpenGL watchface

Stores the watchface image into the frame, and overlays whatever data needs to be put on top of it (for example, "OK, Google" text, battery remaining, notifications, etc)

When the frame is ready to be shown, it sets the framebuffer it was working on as the default one, so the display can show the entire image:

I/DisplayManagerService( 415): Display device changed: DisplayDeviceInfo{"ActivityViewVirtualDisplay": 320 x 320, 60.0 fps, density 240, 240.0 x 240.0 dpi, touch NONE, rotation 0, type VIRTUAL, state ON, owner android (uid 1000), FLAG_OWN_CONTENT_ONLY}

What I think is happening is this:

W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] Unexpected dequeueBuffer() in IDLE state
W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] EGL called dequeueBuffer with !async despite eglSwapInterval(0)
E/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] dequeueBuffer: no buffer, bailing out
E/[EGL-ERROR]( 111): EGLBoolean __egl_platform_create_surface_window(egl_surface*, mali_base_ctx_handle):966: [__egl_platform_create_surface_window]: dequeueBuffer fail on native win 0x40e40e60, buffer 0x0

From all this, the interesting part is in the 'IDLE state'. If the GPU is in an idle state, it shouldn't be doing GL stuff! So the buffer is not allocated, so it crashes. At some point, the GPU stays in a non-idle state and that's where OpenGL allocator stops failing and crashing the frame creation process.

If you take a look at the logcat, you will see that, even though the HWC is still dropping errors, that message STOPS the second the watchface starts working:

V/ActivityManager( 415): Display changed displayId=1
W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] Unexpected dequeueBuffer() in IDLE state
W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] EGL called dequeueBuffer with !async despite eglSwapInterval(0)
E/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] dequeueBuffer: no buffer, bailing out
E/[EGL-ERROR]( 111): EGLBoolean __egl_platform_create_surface_window(egl_surface*, mali_base_ctx_handle):966: [__egl_platform_create_surface_window]: dequeueBuffer fail on native win 0x40e40e60, buffer 0x0
E/libEGL ( 111): eglQuerySurface:590 error 300d (EGL_BAD_SURFACE)
E/libEGL ( 111): eglQuerySurface:590 error 300d (EGL_BAD_SURFACE)
// HERE IT STARTS WORKING

W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] Unexpected beginFrame() in GLES state
E/libEGL ( 111): eglMakeCurrent:775 error 3009 (EGL_BAD_MATCH)
W/SurfaceFlinger( 111): DisplayDevice::makeCurrent failed. Aborting surface composition for display ActivityViewVirtualDisplay
E/libEGL ( 111): eglSwapBuffers:1051 error 300d (EGL_BAD_SURFACE)
E/SurfaceFlinger( 111): eglSwapBuffers(0x1, 0x0) failed with 0x0000300d
W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] Unexpected advanceFrame() in PREPARED state on GLES/MIXED frame
E/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] advanceFrame: no buffer, bailing out
E/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] failed pushing new frame to HWC: -12
E/bt_upio ( 748): upio_set : open(/proc/bluetooth/sleep/btwrite) for write failed: No such file or directory (2)
E/libEGL ( 111): eglMakeCurrent:775 error 3009 (EGL_BAD_MATCH)
W/SurfaceFlinger( 111): DisplayDevice::makeCurrent failed. Aborting surface composition for display ActivityViewVirtualDisplay
E/libEGL ( 111): eglSwapBuffers:1051 error 300d (EGL_BAD_SURFACE)
E/SurfaceFlinger( 111): eglSwapBuffers(0x1, 0x0) failed with 0x0000300d
W/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] Unexpected advanceFrame() in PREPARED state on GLES/MIXED frame
E/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] advanceFrame: no buffer, bailing out
E/SurfaceFlinger( 111): [ActivityViewVirtualDisplay] failed pushing new frame to HWC: -12
E/libEGL ( 111): eglMakeCurrent:775 error 3009 (EGL_BAD_MATCH)

If my theory is correct, this problem might come from the exynos power management on Mali, which comes directly from the Tizen kernel release. (Kernel: /drivers/gpu/arm/mali400/r4p0_rel0/platform/exynos3250/exynos4_pmm.c) and/or one of the non-gpl-compliant power management functions that are in use on the Mali driver right now (I saw errors with it when I tried to make the AOSP tree compile the kernel)

I tried some modifications on the kernel settings but so far I didn't catch it... will keep trying!