forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathandroid_external_texture_gl.cc
More file actions
119 lines (103 loc) · 3.93 KB
/
android_external_texture_gl.cc
File metadata and controls
119 lines (103 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// 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 "flutter/shell/platform/android/platform_view_android_jni.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
namespace shell {
AndroidExternalTextureGL::AndroidExternalTextureGL(
int64_t id,
const fml::jni::JavaObjectWeakGlobalRef& surfaceTexture)
: Texture(id), surface_texture_(surfaceTexture), transform(SkMatrix::I()) {}
AndroidExternalTextureGL::~AndroidExternalTextureGL() = default;
void AndroidExternalTextureGL::OnGrContextCreated() {
state_ = AttachmentState::uninitialized;
}
void AndroidExternalTextureGL::MarkNewFrameAvailable() {
new_frame_ready_ = true;
}
void AndroidExternalTextureGL::Paint(SkCanvas& canvas,
const SkRect& bounds,
bool freeze) {
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);
}
canvas.drawImage(image, 0, 0);
}
}
void AndroidExternalTextureGL::UpdateTransform() {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> surfaceTexture =
surface_texture_.get(env);
fml::jni::ScopedJavaLocalRef<jfloatArray> transformMatrix(
env, env->NewFloatArray(16));
SurfaceTextureGetTransformMatrix(env, surfaceTexture.obj(),
transformMatrix.obj());
float* m = env->GetFloatArrayElements(transformMatrix.obj(), nullptr);
SkScalar matrix3[] = {
m[0], m[1], m[2], //
m[4], m[5], m[6], //
m[8], m[9], m[10], //
};
env->ReleaseFloatArrayElements(transformMatrix.obj(), m, JNI_ABORT);
transform.set9(matrix3);
}
void AndroidExternalTextureGL::OnGrContextDestroyed() {
if (state_ == AttachmentState::attached) {
Detach();
}
state_ = AttachmentState::detached;
}
void AndroidExternalTextureGL::Attach(jint textureName) {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> surfaceTexture =
surface_texture_.get(env);
if (!surfaceTexture.is_null()) {
SurfaceTextureAttachToGLContext(env, surfaceTexture.obj(), textureName);
}
}
void AndroidExternalTextureGL::Update() {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> surfaceTexture =
surface_texture_.get(env);
if (!surfaceTexture.is_null()) {
SurfaceTextureUpdateTexImage(env, surfaceTexture.obj());
UpdateTransform();
}
}
void AndroidExternalTextureGL::Detach() {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> surfaceTexture =
surface_texture_.get(env);
if (!surfaceTexture.is_null()) {
SurfaceTextureDetachFromGLContext(env, surfaceTexture.obj());
}
}
} // namespace shell