#include "flutter/shell/platform/ohos/ohos_surface_gl.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/memory/ref_ptr.h"
namespace flutter {
OhosSurfaceGL::OhosSurfaceGL()
: window_(nullptr),
eglRenderSurface_(nullptr),
eglDisplay_(nullptr),
eglContext_(nullptr),
eglSurface_(nullptr),
valid_(false)
{
FML_LOG(ERROR) << "OhosSurfaceGL Constructor";
}
bool OhosSurfaceGL::IsValid() const
{
return valid_;
}
std::unique_ptr<Surface> OhosSurfaceGL::CreateGPUSurface()
{
auto surface = std::make_unique<GPUSurfaceGL>(this, true);
return surface->IsValid() ? std::move(surface) : nullptr;
}
void OhosSurfaceGL::SetPlatformWindow(const OHOS::sptr<OHOS::Rosen::Window>& window)
{
if (window == nullptr) {
FML_LOG(ERROR) << "Ohos window is nullptr";
return;
}
window_ = window;
if (!this->InitRenderSurface()) {
FML_LOG(ERROR) << "Failed to init render surface.";
}
}
bool OhosSurfaceGL::OnScreenSurfaceResize(const SkISize& size)
{
if (!IsValid()) {
FML_LOG(ERROR) << "OnScreenSurfaceResize surface invalid";
return false;
}
eglRenderSurface_->SetWidthAndHeight(size.width(), size.height());
return true;
}
void OhosSurfaceGL::TeardownOnScreenContext()
{
if (!IsValid()) {
FML_LOG(ERROR) << "TeardownOnScreenContext surface invalid";
return;
}
if (eglGetCurrentContext() != eglContext_) {
FML_LOG(INFO) << "Egl context is diff";
return;
}
if (eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
FML_LOG(ERROR) << "Could not clear the current context";
return;
}
}
bool OhosSurfaceGL::ResourceContextMakeCurrent()
{
return false;
}
bool OhosSurfaceGL::ResourceContextClearCurrent()
{
return false;
}
bool OhosSurfaceGL::GLContextPresent()
{
if (!IsValid()) {
FML_LOG(ERROR) << "GLContextPresent surface invalid";
return false;
}
OHOS::SurfaceError errorCode = eglRenderSurface_->SwapBuffers();
if (errorCode != OHOS::SURFACE_ERROR_OK) {
FML_LOG(ERROR) << "Failed to swap buffers. code is " << errorCode;
return false;
}
return true;
}
intptr_t OhosSurfaceGL::GLContextFBO() const
{
if (!IsValid()) {
FML_LOG(ERROR) << "GLContextFBO surface invalid";
return 0;
}
return static_cast<intptr_t>(eglRenderSurface_->GetEglFbo());
}
bool OhosSurfaceGL::GLContextFBOResetAfterPresent() const
{
return true;
}
bool OhosSurfaceGL::UseOffscreenSurface() const
{
return true;
}
SkMatrix OhosSurfaceGL::GLContextSurfaceTransformation() const
{
SkMatrix matrix;
matrix.setIdentity();
double y = window_->GetRect().height_ / 2.0;
matrix.postTranslate(0, -y);
matrix.postScale(1, -1);
matrix.postTranslate(0, y);
return matrix;
}
bool OhosSurfaceGL::GLContextMakeCurrent()
{
if (!IsValid()) {
FML_LOG(ERROR) << "GLContextMakeCurrent surface invalid";
return false;
}
if (eglGetCurrentContext() == eglContext_) {
FML_LOG(INFO) << "Egl context is same";
return true;
}
if ((eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_) != EGL_TRUE)) {
FML_LOG(ERROR) << "Could not make the context current. code is " << eglGetError();
return false;
}
return true;
}
bool OhosSurfaceGL::GLContextClearCurrent()
{
if (!IsValid()) {
FML_LOG(ERROR) << "GLContextClearCurrent surface invalid";
return false;
}
if (eglGetCurrentContext() != eglContext_) {
FML_LOG(INFO) << "Egl context is diff";
return true;
}
if (eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
FML_LOG(ERROR) << "Could not clear the current context. code is " << eglGetError();
return false;
}
return true;
}
ExternalViewEmbedder* OhosSurfaceGL::GetExternalViewEmbedder()
{
return nullptr;
}
bool OhosSurfaceGL::InitRenderSurface()
{
if (!window_) {
FML_LOG(ERROR) << "window_ is nullptr";
return false;
}
auto surfaceNode = window_->GetSurfaceNode();
if (!surfaceNode) {
FML_LOG(ERROR) << "surface node is null";
return false;
}
auto surface = surfaceNode->GetSurface();
if (!surface) {
FML_LOG(ERROR) << "surface is null";
return false;
}
OHOS::sptr<OHOS::IBufferProducer> bufferProducer = surface->GetProducer();
if (bufferProducer == nullptr) {
FML_LOG(ERROR) << "bufferProducer is nullptr";
return false;
}
eglRenderSurface_ = OHOS::EglRenderSurface::CreateEglRenderSurfaceAsProducer(bufferProducer);
if (eglRenderSurface_ == nullptr) {
FML_LOG(ERROR) << "eglRenderSurface_ is nullptr";
return false;
}
OHOS::SurfaceError errorCode = eglRenderSurface_->InitContext();
if (errorCode != OHOS::SURFACE_ERROR_OK) {
FML_LOG(ERROR) << "Failed to init render context. code is " << errorCode;
return false;
}
if ((eglGetCurrentContext() == eglContext_) &&
(eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)) {
FML_LOG(ERROR) << "Could not clear the current context. code is " << eglGetError();
}
eglDisplay_ = eglRenderSurface_->GetEglDisplay();
if (eglDisplay_ == EGL_NO_DISPLAY) {
FML_LOG(ERROR) << "EglDisplay_ is nullptr";
return false;
}
eglContext_ = eglRenderSurface_->GetEglContext();
if (eglContext_ == EGL_NO_CONTEXT) {
FML_LOG(ERROR) << "EglContext_ is nullptr";
return false;
}
eglSurface_ = eglRenderSurface_->GetEglSurface();
valid_ = true;
return true;
}
}