Flutter Engine
The Flutter Engine
EGLImageTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "tests/Test.h"
10
11
12#ifdef SK_GL
21#include "include/gpu/GrTypes.h"
31#include "src/gpu/Swizzle.h"
42#include "src/gpu/ganesh/SurfaceFillContext.h" // IWYU pragma: keep
48#include "tests/TestUtils.h"
51
52#include <cstdint>
53#include <memory>
54#include <utility>
55
56using namespace skia_private;
57
58struct GrContextOptions;
59
61
62static void cleanup(GLTestContext* glctx0,
63 GrGLuint texID0,
64 GLTestContext* glctx1,
65 const sk_sp<GrDirectContext>& dContext,
66 GrEGLImage image1) {
67 if (glctx1) {
68 glctx1->makeCurrent();
69 if (GR_EGL_NO_IMAGE != image1) {
70 glctx1->destroyEGLImage(image1);
71 }
72 }
73
74 glctx0->makeCurrent();
75 if (texID0) {
76 GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0));
77 }
78}
79
81 auto context0 = ctxInfo.directContext();
82 sk_gpu_test::GLTestContext* glCtx0 = ctxInfo.glContext();
83
84 // Try to create a second GL context and then check if the contexts have necessary
85 // extensions to run this test.
86
87 if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) {
88 return;
89 }
90 GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->priv().getGpu());
92 return;
93 }
94
95 std::unique_ptr<GLTestContext> glCtx1 = glCtx0->makeNew();
96 if (!glCtx1) {
97 return;
98 }
101 GrGLTextureInfo externalTexture;
102 externalTexture.fID = 0;
103
104 if (!context1) {
105 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
106 return;
107 }
108
109 if (!glCtx1->gl()->hasExtension("EGL_KHR_image") ||
110 !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
111 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
112 return;
113 }
114
115 ///////////////////////////////// CONTEXT 1 ///////////////////////////////////
116
117 // Use GL Context 1 to create a texture unknown to context 0.
118 context1->flushAndSubmit();
119 static const int kSize = 100;
120
121 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(context1.get(),
122 kSize,
123 kSize,
128
129 if (!mbet) {
130 ERRORF(reporter, "Error creating texture for EGL Image");
131 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
132 return;
133 }
134
135 GrGLTextureInfo texInfo;
136 if (!GrBackendTextures::GetGLTextureInfo(mbet->texture(), &texInfo)) {
137 ERRORF(reporter, "Failed to get GrGLTextureInfo");
138 return;
139 }
140
141 if (GR_GL_TEXTURE_2D != texInfo.fTarget) {
142 ERRORF(reporter, "Expected backend texture to be 2D");
143 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
144 return;
145 }
146
147 // Wrap the texture in an EGLImage
148 image = glCtx1->texture2DToEGLImage(texInfo.fID);
149 if (GR_EGL_NO_IMAGE == image) {
150 ERRORF(reporter, "Error creating EGL Image from texture");
151 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
152 return;
153 }
154
155 // Since we are dealing with two different GL contexts here, we need to call finish so that the
156 // clearing of the texture that happens in createTextingOnlyBackendTexture occurs before we call
157 // TexSubImage below on the other context. Otherwise, it is possible the calls get reordered and
158 // the clearing overwrites the TexSubImage writes.
159 GR_GL_CALL(glCtx1->gl(), Finish());
160
161 // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans
162 // the EGL image. Also, this must be done after creating the EGLImage as the texture
163 // contents may not be preserved when the image is created.
165 for (int i = 0; i < kSize*kSize; ++i) {
166 pixels.get()[i] = 0xDDAABBCC;
167 }
168 GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0));
169 GR_GL_CALL(glCtx1->gl(), BindTexture(texInfo.fTarget, texInfo.fID));
170 GR_GL_CALL(glCtx1->gl(), TexSubImage2D(texInfo.fTarget, 0, 0, 0, kSize, kSize,
171 GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get()));
172 GR_GL_CALL(glCtx1->gl(), Finish());
173 // We've been making direct GL calls in GL context 1, let GrDirectContext 1 know its internal
174 // state is invalid.
175 context1->resetContext();
176
177 ///////////////////////////////// CONTEXT 0 ///////////////////////////////////
178
179 // Make a new texture ID in GL Context 0 from the EGL Image
180 glCtx0->makeCurrent();
181 externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL;
182 externalTexture.fID = glCtx0->eglImageToExternalTexture(image);
183 externalTexture.fFormat = GR_GL_RGBA8;
184 if (0 == externalTexture.fID) {
185 ERRORF(reporter, "Error converting EGL Image back to texture");
186 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
187 return;
188 }
189
190 // Wrap this texture ID in a GrTexture
191 GrBackendTexture backendTex =
193
195 // TODO: If I make this TopLeft origin to match resolve_origin calls for kDefault, this test
196 // fails on the Nexus5. Why?
198 sk_sp<GrSurfaceProxy> texProxy = context0->priv().proxyProvider()->wrapBackendTexture(
200 if (!texProxy) {
201 ERRORF(reporter, "Error wrapping external texture in GrTextureProxy.");
202 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
203 return;
204 }
205 skgpu::Swizzle swizzle = context0->priv().caps()->getReadSwizzle(texProxy->backendFormat(),
206 colorInfo.colorType());
207 GrSurfaceProxyView view(std::move(texProxy), origin, swizzle);
208 auto surfaceContext = context0->priv().makeSC(std::move(view), colorInfo);
209
210 if (!surfaceContext) {
211 ERRORF(reporter, "Error wrapping external texture in SurfaceContext.");
212 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
213 return;
214 }
215
216 GrTextureProxy* proxy = surfaceContext->asTextureProxy();
219
224
225 // Should not be able to wrap as a RT
226 {
227 auto temp = context0->priv().makeSFCFromBackendTexture(colorInfo,
228 backendTex,
229 1,
230 origin,
231 /*release helper*/ nullptr);
232 if (temp) {
233 ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT.");
234 }
235 }
236
237 //TestReadPixels(reporter, context0, surfaceContext.get(), pixels.get(), "EGLImageTest-read");
238
239 // We should not be able to write to an EXTERNAL texture
240 TestWritePixels(reporter, context0, surfaceContext.get(), false, "EGLImageTest-write");
241
242 // Only test RT-config
243 // TODO: why do we always need to draw to copy from an external texture?
245 context0,
246 surfaceContext->asSurfaceProxyRef(),
247 surfaceContext->origin(),
248 colorInfo.colorType(),
249 pixels.get(),
250 "EGLImageTest-copy");
251
252 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
253}
254
255#endif // SK_GL
reporter
Definition: FontMgrTest.cpp:39
#define GR_GL_RGBA
Definition: GrGLDefines.h:441
#define GR_EGL_NO_IMAGE
Definition: GrGLDefines.h:1124
#define GR_GL_RGBA8
Definition: GrGLDefines.h:524
#define GR_GL_TEXTURE_2D
Definition: GrGLDefines.h:152
#define GR_GL_TEXTURE0
Definition: GrGLDefines.h:651
#define GR_GL_UNSIGNED_BYTE
Definition: GrGLDefines.h:350
#define GR_GL_TEXTURE_EXTERNAL
Definition: GrGLDefines.h:1052
unsigned int GrGLuint
Definition: GrGLTypes.h:113
@ kGLES_GrGLStandard
Definition: GrGLTypes.h:22
void * GrEGLImage
Definition: GrGLTypes.h:165
#define GR_GL_CALL(IFACE, X)
Definition: GrGLUtil.h:381
@ kRW_GrIOType
Definition: GrTypesPriv.h:405
@ kBorrow_GrWrapOwnership
Definition: GrTypesPriv.h:79
GrSurfaceOrigin
Definition: GrTypes.h:147
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
void TestWritePixels(skiatest::Reporter *reporter, GrDirectContext *dContext, skgpu::ganesh::SurfaceContext *dstContext, bool expectedToWork, const char *testName)
Definition: TestUtils.cpp:66
void TestCopyFromSurface(skiatest::Reporter *reporter, GrDirectContext *dContext, sk_sp< GrSurfaceProxy > proxy, GrSurfaceOrigin origin, GrColorType colorType, uint32_t expectedPixelValues[], const char *testName)
Definition: TestUtils.cpp:98
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define DEF_GANESH_TEST_FOR_GL_CONTEXT(name, reporter, context_info, ctsEnforcement)
Definition: Test.h:442
#define ERRORF(r,...)
Definition: Test.h:293
const GrShaderCaps * shaderCaps() const
Definition: GrCaps.h:63
void resetContext(uint32_t state=kAll_GrBackendState)
void flushAndSubmit(GrSyncCpu sync=GrSyncCpu::kNo)
const GrGLCaps & glCaps() const
Definition: GrGLGpu.h:108
const GrBackendFormat & backendFormat() const
GrSurfaceProxyPriv priv()
GrTexture * peekTexture() const
GrTextureType textureType() const
bool hasRestrictedSampling() const
skgpu::Mipmapped mipmapped() const
GrTextureProxy * asTextureProxy() override
skgpu::Mipmapped mipmapped() const
Definition: GrTexture.h:62
bool hasRestrictedSampling() const
Definition: GrTexture.h:56
GrTextureType textureType() const
Definition: GrTexture.h:55
virtual std::unique_ptr< GLTestContext > makeNew() const
Definition: GLTestContext.h:51
virtual GrGLuint eglImageToExternalTexture(GrEGLImage) const
Definition: GLTestContext.h:41
const GrGLInterface * gl() const
Definition: GLTestContext.h:30
T * get() const
Definition: SkRefCnt.h:303
constexpr int kSize
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
SK_API bool GetGLTextureInfo(const GrBackendTexture &, GrGLTextureInfo *)
SK_API sk_sp< GrDirectContext > MakeGL(sk_sp< const GrGLInterface >, const GrContextOptions &)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
static void Finish(Thread *thread)
Definition: bootstrap.cc:44
GrGLStandard fStandard
Definition: GrGLInterface.h:81
GrGLuint fID
Definition: GrGLTypes.h:182
GrGLenum fFormat
Definition: GrGLTypes.h:183
GrGLenum fTarget
Definition: GrGLTypes.h:181
bool fExternalTextureSupport
Definition: SkSLUtil.h:99