Skip to content

Commit

Permalink
[XB1] Add EGL_CONTEXT_LOST handler extension
Browse files Browse the repository at this point in the history
This change adds handler extension that triggers graphics recreation if EGL_CONTEXT_LOST error occurred.

b/329326128
  • Loading branch information
alexanderbobrovnik committed Jan 28, 2025
1 parent aa30fce commit 6f0c36e
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 0 deletions.
19 changes: 19 additions & 0 deletions cobalt/renderer/backend/egl/graphics_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "cobalt/renderer/backend/egl/utils.h"
#include "cobalt/renderer/egl_and_gles.h"
#include "starboard/configuration.h"
#include "starboard/extension/egl_context_lost_handler.h"

#if defined(GLES3_SUPPORTED)
#error "Support for gles3 features has been deprecated."
Expand Down Expand Up @@ -251,6 +252,9 @@ void GraphicsContextEGL::SafeEglMakeCurrent(RenderTargetEGL* surface) {
// a thread can result in global allocations being made that are never freed.
ANNOTATE_SCOPED_MEMORY_LEAK;

if (error_context_lost_) {
return;
}
EGLSurface egl_surface = surface->GetSurface();

// This should only be used with egl surfaces (not framebuffer objects).
Expand Down Expand Up @@ -279,6 +283,21 @@ void GraphicsContextEGL::SafeEglMakeCurrent(RenderTargetEGL* surface) {
surface->set_surface_bad();
egl_surface = null_surface_->GetSurface();
EGL_CALL(eglMakeCurrent(display_, egl_surface, egl_surface, context_));
} else if (make_current_error == EGL_CONTEXT_LOST) {
const CobaltExtensionEglContextLostHandlerApi* context_lost_handler =
static_cast<const CobaltExtensionEglContextLostHandlerApi*>(
SbSystemGetExtension(kCobaltExtensionEglContextLostHandlerName));
if (context_lost_handler &&
strcmp(context_lost_handler->name,
kCobaltExtensionEglContextLostHandlerName) == 0 &&
context_lost_handler->version >= 1) {
error_context_lost_ = true;
EGL_CALL(eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT));
context_lost_handler->HandleEglContextLost();
} else {
NOTREACHED() << "EGL_CONTEXT_LOST when calling eglMakeCurrent().";
}
} else {
NOTREACHED() << "Unexpected error when calling eglMakeCurrent().";
}
Expand Down
2 changes: 2 additions & 0 deletions cobalt/renderer/backend/egl/graphics_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ class GraphicsContextEGL : public GraphicsContext {
// OpenGL ES implementation.
bool bgra_format_supported_;

bool error_context_lost_ = false;

// Data required to provide BlitToRenderTarget() functionality via OpenGL ES.
GLuint blit_vertex_shader_;
GLuint blit_fragment_shader_;
Expand Down
46 changes: 46 additions & 0 deletions starboard/extension/egl_context_lost_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2025 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef STARBOARD_EXTENSION_EGL_CONTEXT_LOST_HANDLER_H_
#define STARBOARD_EXTENSION_EGL_CONTEXT_LOST_HANDLER_H_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define kCobaltExtensionEglContextLostHandlerName \
"dev.cobalt.extension.EglContextLostHandler"

typedef struct CobaltExtensionEglContextLostHandlerApi {
// Name should be the string |kCobaltExtensionEglContextLostHandlerName|.
// This helps to validate that the extension API is correct.
const char* name;

// This specifies the version of the API that is implemented.
uint32_t version;

// The fields below this point were added in version 1 or later.

// Called when EGL_CONTEXT_LOST error is detected.
void (*HandleEglContextLost)();

} CobaltExtensionEglContextLostHandlerApi;

#ifdef __cplusplus
} // extern "C"
#endif

#endif // STARBOARD_EXTENSION_EGL_CONTEXT_LOST_HANDLER_H_
21 changes: 21 additions & 0 deletions starboard/extension/extension_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "starboard/extension/configuration.h"
#include "starboard/extension/crash_handler.h"
#include "starboard/extension/cwrappers.h"
#include "starboard/extension/egl_context_lost_handler.h"
#include "starboard/extension/enhanced_audio.h"
#include "starboard/extension/font.h"
#include "starboard/extension/free_space.h"
Expand Down Expand Up @@ -527,5 +528,25 @@ TEST(ExtensionTest, PlayerConfiguration) {
}
}

TEST(ExtensionTest, EglContextLostHandler) {
typedef CobaltExtensionEglContextLostHandlerApi ExtensionApi;
const char* kExtensionName = kCobaltExtensionEglContextLostHandlerName;

const ExtensionApi* extension_api =
static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
if (!extension_api) {
return;
}

EXPECT_STREQ(extension_api->name, kExtensionName);
EXPECT_EQ(extension_api->version, 1u);
EXPECT_NE(extension_api->HandleEglContextLost, nullptr);

const ExtensionApi* second_extension_api =
static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName));
EXPECT_EQ(second_extension_api, extension_api)
<< "Extension struct should be a singleton";
}

} // namespace extension
} // namespace starboard
2 changes: 2 additions & 0 deletions starboard/xb1/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ static_library("starboard_platform") {
"shared/configuration.cc",
"shared/configuration.h",
"shared/configuration_constants.cc",
"shared/egl_context_lost_handler.cc",
"shared/egl_context_lost_handler.h",
"shared/system_get_extensions.cc",
"shared/system_get_path.cc",
]
Expand Down
61 changes: 61 additions & 0 deletions starboard/xb1/shared/egl_context_lost_handler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2025 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/xb1/shared/egl_context_lost_handler.h"

#include "starboard/extension/egl_context_lost_handler.h"
#include "starboard/shared/starboard/media/mime_supportability_cache.h"
#include "starboard/shared/uwp/application_uwp.h"

using starboard::shared::starboard::media::MimeSupportabilityCache;
using starboard::shared::uwp::ApplicationUwp;

namespace starboard {
namespace xb1 {
namespace shared {

namespace {

void HandleEglContextLost() {
MimeSupportabilityCache::GetInstance()->ClearCachedMimeSupportabilities();
ApplicationUwp::Get()->Inject(
new ApplicationUwp::Event(kSbEventTypeBlur, NULL, NULL));
ApplicationUwp::Get()->Inject(
new ApplicationUwp::Event(kSbEventTypeConceal, NULL, NULL));
ApplicationUwp::Get()->Inject(
new ApplicationUwp::Event(kSbEventTypeFreeze, NULL, NULL));

ApplicationUwp::Get()->Inject(
new ApplicationUwp::Event(kSbEventTypeUnfreeze, NULL, NULL));
ApplicationUwp::Get()->Inject(
new ApplicationUwp::Event(kSbEventTypeReveal, NULL, NULL));
ApplicationUwp::Get()->Inject(
new ApplicationUwp::Event(kSbEventTypeFocus, NULL, NULL));
}

const CobaltExtensionEglContextLostHandlerApi kEglContextLostHandlerApi = {
kCobaltExtensionEglContextLostHandlerName,
1,
&HandleEglContextLost,
};

} // namespace

const void* GetEglContextLostHandlerApi() {
return &kEglContextLostHandlerApi;
}

} // namespace shared
} // namespace xb1
} // namespace starboard
28 changes: 28 additions & 0 deletions starboard/xb1/shared/egl_context_lost_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2025 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef STARBOARD_XB1_SHARED_EGL_CONTEXT_LOST_HANDLER_H_
#define STARBOARD_XB1_SHARED_EGL_CONTEXT_LOST_HANDLER_H_

namespace starboard {
namespace xb1 {
namespace shared {

const void* GetEglContextLostHandlerApi();

} // namespace shared
} // namespace xb1
} // namespace starboard

#endif // STARBOARD_XB1_SHARED_EGL_CONTEXT_LOST_HANDLER_H_
5 changes: 5 additions & 0 deletions starboard/xb1/shared/system_get_extensions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@

#include "starboard/common/string.h"
#include "starboard/extension/configuration.h"
#include "starboard/extension/egl_context_lost_handler.h"
#include "starboard/extension/graphics.h"
#include "starboard/extension/media_session.h"
#include "starboard/shared/uwp/xb1_media_session_client.h"
#include "starboard/shared/win32/graphics.h"
#include "starboard/xb1/shared/configuration.h"
#include "starboard/xb1/shared/egl_context_lost_handler.h"

const void* SbSystemGetExtension(const char* name) {
if (strcmp(name, kCobaltExtensionGraphicsName) == 0) {
Expand All @@ -32,5 +34,8 @@ const void* SbSystemGetExtension(const char* name) {
if (strcmp(name, kCobaltExtensionMediaSessionName) == 0) {
return starboard::shared::uwp::GetMediaSessionApi();
}
if (strcmp(name, kCobaltExtensionEglContextLostHandlerName) == 0) {
return starboard::xb1::shared::GetEglContextLostHandlerApi();
}
return NULL;
}

0 comments on commit 6f0c36e

Please sign in to comment.