|  | // Copyright 2013 The Flutter Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "flutter/shell/platform/windows/external_texture_d3d.h" | 
|  |  | 
|  | #include "flutter/fml/logging.h" | 
|  | #include "flutter/shell/platform/embedder/embedder_struct_macros.h" | 
|  |  | 
|  | namespace flutter { | 
|  |  | 
|  | ExternalTextureD3d::ExternalTextureD3d( | 
|  | FlutterDesktopGpuSurfaceType type, | 
|  | const FlutterDesktopGpuSurfaceTextureCallback texture_callback, | 
|  | void* user_data, | 
|  | const egl::Manager* egl_manager, | 
|  | std::shared_ptr<egl::ProcTable> gl) | 
|  | : type_(type), | 
|  | texture_callback_(texture_callback), | 
|  | user_data_(user_data), | 
|  | egl_manager_(egl_manager), | 
|  | gl_(std::move(gl)) {} | 
|  |  | 
|  | ExternalTextureD3d::~ExternalTextureD3d() { | 
|  | ReleaseImage(); | 
|  |  | 
|  | if (gl_texture_ != 0) { | 
|  | gl_->DeleteTextures(1, &gl_texture_); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool ExternalTextureD3d::PopulateTexture(size_t width, | 
|  | size_t height, | 
|  | FlutterOpenGLTexture* opengl_texture) { | 
|  | const FlutterDesktopGpuSurfaceDescriptor* descriptor = | 
|  | texture_callback_(width, height, user_data_); | 
|  |  | 
|  | if (!CreateOrUpdateTexture(descriptor)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Populate the texture object used by the engine. | 
|  | opengl_texture->target = GL_TEXTURE_2D; | 
|  | opengl_texture->name = gl_texture_; | 
|  | opengl_texture->format = GL_RGBA8_OES; | 
|  | opengl_texture->destruction_callback = nullptr; | 
|  | opengl_texture->user_data = nullptr; | 
|  | opengl_texture->width = SAFE_ACCESS(descriptor, visible_width, 0); | 
|  | opengl_texture->height = SAFE_ACCESS(descriptor, visible_height, 0); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void ExternalTextureD3d::ReleaseImage() { | 
|  | if (egl_surface_ != EGL_NO_SURFACE) { | 
|  | eglReleaseTexImage(egl_manager_->egl_display(), egl_surface_, | 
|  | EGL_BACK_BUFFER); | 
|  | eglDestroySurface(egl_manager_->egl_display(), egl_surface_); | 
|  | egl_surface_ = EGL_NO_SURFACE; | 
|  | } | 
|  | } | 
|  |  | 
|  | bool ExternalTextureD3d::CreateOrUpdateTexture( | 
|  | const FlutterDesktopGpuSurfaceDescriptor* descriptor) { | 
|  | if (descriptor == nullptr || | 
|  | SAFE_ACCESS(descriptor, handle, nullptr) == nullptr) { | 
|  | ReleaseImage(); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (gl_texture_ == 0) { | 
|  | gl_->GenTextures(1, &gl_texture_); | 
|  |  | 
|  | gl_->BindTexture(GL_TEXTURE_2D, gl_texture_); | 
|  | gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
|  | gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
|  | gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
|  | gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
|  | } else { | 
|  | gl_->BindTexture(GL_TEXTURE_2D, gl_texture_); | 
|  | } | 
|  |  | 
|  | auto handle = SAFE_ACCESS(descriptor, handle, nullptr); | 
|  | if (handle != last_surface_handle_) { | 
|  | ReleaseImage(); | 
|  |  | 
|  | EGLint attributes[] = { | 
|  | EGL_WIDTH, | 
|  | static_cast<EGLint>(SAFE_ACCESS(descriptor, width, 0)), | 
|  | EGL_HEIGHT, | 
|  | static_cast<EGLint>(SAFE_ACCESS(descriptor, height, 0)), | 
|  | EGL_TEXTURE_TARGET, | 
|  | EGL_TEXTURE_2D, | 
|  | EGL_TEXTURE_FORMAT, | 
|  | EGL_TEXTURE_RGBA,  // always EGL_TEXTURE_RGBA | 
|  | EGL_NONE}; | 
|  |  | 
|  | egl_surface_ = egl_manager_->CreateSurfaceFromHandle( | 
|  | (type_ == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D) | 
|  | ? EGL_D3D_TEXTURE_ANGLE | 
|  | : EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, | 
|  | handle, attributes); | 
|  |  | 
|  | if (egl_surface_ == EGL_NO_SURFACE || | 
|  | eglBindTexImage(egl_manager_->egl_display(), egl_surface_, | 
|  | EGL_BACK_BUFFER) == EGL_FALSE) { | 
|  | FML_LOG(ERROR) << "Binding D3D surface failed."; | 
|  | } | 
|  | last_surface_handle_ = handle; | 
|  | } | 
|  |  | 
|  | auto release_callback = SAFE_ACCESS(descriptor, release_callback, nullptr); | 
|  | if (release_callback) { | 
|  | release_callback(SAFE_ACCESS(descriptor, release_context, nullptr)); | 
|  | } | 
|  | return egl_surface_ != EGL_NO_SURFACE; | 
|  | } | 
|  |  | 
|  | }  // namespace flutter |