blob: 00befbad243a693fed11d11c7be7687dbc11c34e [file] [log] [blame]
// 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/android/android_external_texture_gl.h"
#include <GLES/glext.h>
#include "third_party/skia/include/gpu/GrBackendSurface.h"
namespace flutter {
AndroidExternalTextureGL::AndroidExternalTextureGL(
int64_t id,
const fml::jni::JavaObjectWeakGlobalRef& surface_texture,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: Texture(id),
jni_facade_(jni_facade),
surface_texture_(surface_texture),
transform(SkMatrix::I()) {}
AndroidExternalTextureGL::~AndroidExternalTextureGL() {
if (state_ == AttachmentState::attached) {
glDeleteTextures(1, &texture_name_);
}
}
void AndroidExternalTextureGL::OnGrContextCreated() {
state_ = AttachmentState::uninitialized;
}
void AndroidExternalTextureGL::MarkNewFrameAvailable() {
new_frame_ready_ = true;
}
void AndroidExternalTextureGL::Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze,
GrContext* context,
SkFilterQuality filter_quality) {
if (state_ == AttachmentState::detached) {
return;
}
if (state_ == AttachmentState::uninitialized) {
glGenTextures(1, &texture_name_);
Attach(static_cast<jint>(texture_name_));
state_ = AttachmentState::attached;
}
if (!freeze && new_frame_ready_) {
Update();
new_frame_ready_ = false;
}
GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_name_,
GL_RGBA8_OES};
GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo);
sk_sp<SkImage> image = SkImage::MakeFromTexture(
canvas.getGrContext(), backendTexture, kTopLeft_GrSurfaceOrigin,
kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
if (image) {
SkAutoCanvasRestore autoRestore(&canvas, true);
canvas.translate(bounds.x(), bounds.y());
canvas.scale(bounds.width(), bounds.height());
if (!transform.isIdentity()) {
SkMatrix transformAroundCenter(transform);
transformAroundCenter.preTranslate(-0.5, -0.5);
transformAroundCenter.postScale(1, -1);
transformAroundCenter.postTranslate(0.5, 0.5);
canvas.concat(transformAroundCenter);
}
SkPaint paint;
paint.setFilterQuality(filter_quality);
canvas.drawImage(image, 0, 0, &paint);
}
}
void AndroidExternalTextureGL::UpdateTransform() {
jni_facade_->SurfaceTextureGetTransformMatrix(surface_texture_, transform);
}
void AndroidExternalTextureGL::OnGrContextDestroyed() {
if (state_ == AttachmentState::attached) {
Detach();
}
state_ = AttachmentState::detached;
}
void AndroidExternalTextureGL::Attach(jint textureName) {
jni_facade_->SurfaceTextureAttachToGLContext(surface_texture_, textureName);
}
void AndroidExternalTextureGL::Update() {
jni_facade_->SurfaceTextureUpdateTexImage(surface_texture_);
UpdateTransform();
}
void AndroidExternalTextureGL::Detach() {
jni_facade_->SurfaceTextureDetachFromGLContext(surface_texture_);
}
void AndroidExternalTextureGL::OnTextureUnregistered() {}
} // namespace flutter