blob: 7e357545084d99538e0a3caf412638a38cc32a49 [file] [log] [blame]
bsalomon7ea33f52015-11-22 14:51:00 -08001/*
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
Robert Phillips6d344c32020-07-06 10:56:46 -04008#include "include/gpu/GrDirectContext.h"
Adlai Hollera0693042020-10-14 11:23:11 -04009#include "src/gpu/GrDirectContextPriv.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040010#include "src/gpu/GrProxyProvider.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrShaderCaps.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000012#include "src/gpu/GrTexture.h"
Adlai Holler9e2c50e2021-02-09 14:41:52 -050013#include "src/gpu/GrTextureProxyPriv.h"
Robert Phillipsf3868622021-08-04 13:27:43 -040014#include "src/gpu/SurfaceFillContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/gl/GrGLGpu.h"
16#include "src/gpu/gl/GrGLUtil.h"
17#include "tests/Test.h"
18#include "tests/TestUtils.h"
19#include "tools/gpu/GrContextFactory.h"
Brian Salomon72050802020-10-12 20:45:06 -040020#include "tools/gpu/ManagedBackendTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "tools/gpu/gl/GLTestContext.h"
bsalomon7ea33f52015-11-22 14:51:00 -080022
John Rosascoa9b348f2019-11-08 13:18:15 -080023#ifdef SK_GL
24
bsalomon273c0f52016-03-31 10:59:06 -070025using sk_gpu_test::GLTestContext;
bsalomon3724e572016-03-30 18:56:19 -070026
Brian Salomon72050802020-10-12 20:45:06 -040027static void cleanup(GLTestContext* glctx0,
28 GrGLuint texID0,
29 GLTestContext* glctx1,
30 sk_sp<GrDirectContext> dContext,
Greg Daniel02611d92017-07-25 10:05:01 -040031 GrEGLImage image1) {
bsalomon7ea33f52015-11-22 14:51:00 -080032 if (glctx1) {
33 glctx1->makeCurrent();
bsalomon7ea33f52015-11-22 14:51:00 -080034 if (GR_EGL_NO_IMAGE != image1) {
35 glctx1->destroyEGLImage(image1);
36 }
bsalomon7ea33f52015-11-22 14:51:00 -080037 }
38
39 glctx0->makeCurrent();
40 if (texID0) {
41 GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0));
42 }
43}
44
bsalomon758586c2016-04-06 14:02:39 -070045DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(EGLImageTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -040046 auto context0 = ctxInfo.directContext();
bsalomon8b7451a2016-05-11 06:33:06 -070047 sk_gpu_test::GLTestContext* glCtx0 = ctxInfo.glContext();
bsalomonf2f1c172016-04-05 12:59:06 -070048
kkinnunen59319222015-11-22 23:23:53 -080049 // Try to create a second GL context and then check if the contexts have necessary
50 // extensions to run this test.
bsalomon7ea33f52015-11-22 14:51:00 -080051
kkinnunen59319222015-11-22 23:23:53 -080052 if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) {
53 return;
bsalomon7ea33f52015-11-22 14:51:00 -080054 }
Robert Phillips9da87e02019-02-04 13:26:26 -050055 GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->priv().getGpu());
Brian Salomon1edc5b92016-11-29 13:43:46 -050056 if (!gpu0->glCaps().shaderCaps()->externalTextureSupport()) {
kkinnunen59319222015-11-22 23:23:53 -080057 return;
58 }
59
Ben Wagner145dbcd2016-11-03 14:40:50 -040060 std::unique_ptr<GLTestContext> glCtx1 = glCtx0->makeNew();
kkinnunen59319222015-11-22 23:23:53 -080061 if (!glCtx1) {
62 return;
63 }
Robert Phillipsf4f80112020-07-13 16:13:31 -040064 sk_sp<GrDirectContext> context1 = GrDirectContext::MakeGL(sk_ref_sp(glCtx1->gl()));
kkinnunen59319222015-11-22 23:23:53 -080065 GrEGLImage image = GR_EGL_NO_IMAGE;
66 GrGLTextureInfo externalTexture;
67 externalTexture.fID = 0;
68
69 if (!context1) {
Brian Salomon72050802020-10-12 20:45:06 -040070 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
kkinnunen59319222015-11-22 23:23:53 -080071 return;
72 }
73
74 if (!glCtx1->gl()->hasExtension("EGL_KHR_image") ||
75 !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
Brian Salomon72050802020-10-12 20:45:06 -040076 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
kkinnunen59319222015-11-22 23:23:53 -080077 return;
78 }
79
80 ///////////////////////////////// CONTEXT 1 ///////////////////////////////////
81
Adlai Hollerc95b5892020-08-11 12:02:22 -040082 // Use GL Context 1 to create a texture unknown to context 0.
Greg Daniel0a2464f2020-05-14 15:45:44 -040083 context1->flushAndSubmit();
kkinnunen59319222015-11-22 23:23:53 -080084 static const int kSize = 100;
Greg Danielc1ad77c2020-05-06 11:40:03 -040085
Brian Salomon72050802020-10-12 20:45:06 -040086 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
87 context1.get(), kSize, kSize, kRGBA_8888_SkColorType, GrMipmapped::kNo,
88 GrRenderable::kNo, GrProtected::kNo);
Greg Daniel5366e592018-01-10 09:57:53 -050089
Brian Salomon72050802020-10-12 20:45:06 -040090 if (!mbet) {
kkinnunen59319222015-11-22 23:23:53 -080091 ERRORF(reporter, "Error creating texture for EGL Image");
Brian Salomon72050802020-10-12 20:45:06 -040092 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
kkinnunen59319222015-11-22 23:23:53 -080093 return;
94 }
Robert Phillipsd21b2a52017-12-12 13:01:25 -050095
Greg Daniel52e16d92018-04-10 09:34:07 -040096 GrGLTextureInfo texInfo;
Brian Salomon72050802020-10-12 20:45:06 -040097 if (!mbet->texture().getGLTextureInfo(&texInfo)) {
Greg Daniel52e16d92018-04-10 09:34:07 -040098 ERRORF(reporter, "Failed to get GrGLTextureInfo");
99 return;
100 }
Robert Phillipsd21b2a52017-12-12 13:01:25 -0500101
Greg Daniel52e16d92018-04-10 09:34:07 -0400102 if (GR_GL_TEXTURE_2D != texInfo.fTarget) {
kkinnunen59319222015-11-22 23:23:53 -0800103 ERRORF(reporter, "Expected backend texture to be 2D");
Brian Salomon72050802020-10-12 20:45:06 -0400104 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
kkinnunen59319222015-11-22 23:23:53 -0800105 return;
106 }
107
108 // Wrap the texture in an EGLImage
Greg Daniel52e16d92018-04-10 09:34:07 -0400109 image = glCtx1->texture2DToEGLImage(texInfo.fID);
kkinnunen59319222015-11-22 23:23:53 -0800110 if (GR_EGL_NO_IMAGE == image) {
111 ERRORF(reporter, "Error creating EGL Image from texture");
Brian Salomon72050802020-10-12 20:45:06 -0400112 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
kkinnunen59319222015-11-22 23:23:53 -0800113 return;
114 }
115
Greg Daniel261b8aa2017-10-23 09:37:36 -0400116 // Since we are dealing with two different GL contexts here, we need to call finish so that the
117 // clearing of the texture that happens in createTextingOnlyBackendTexture occurs before we call
118 // TexSubImage below on the other context. Otherwise, it is possible the calls get reordered and
119 // the clearing overwrites the TexSubImage writes.
120 GR_GL_CALL(glCtx1->gl(), Finish());
121
kkinnunen59319222015-11-22 23:23:53 -0800122 // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans
123 // the EGL image. Also, this must be done after creating the EGLImage as the texture
124 // contents may not be preserved when the image is created.
125 SkAutoTMalloc<uint32_t> pixels(kSize * kSize);
126 for (int i = 0; i < kSize*kSize; ++i) {
127 pixels.get()[i] = 0xDDAABBCC;
128 }
129 GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0));
Greg Daniel52e16d92018-04-10 09:34:07 -0400130 GR_GL_CALL(glCtx1->gl(), BindTexture(texInfo.fTarget, texInfo.fID));
131 GR_GL_CALL(glCtx1->gl(), TexSubImage2D(texInfo.fTarget, 0, 0, 0, kSize, kSize,
kkinnunen59319222015-11-22 23:23:53 -0800132 GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get()));
133 GR_GL_CALL(glCtx1->gl(), Finish());
Robert Phillipse94b4e12020-07-23 13:54:35 -0400134 // We've been making direct GL calls in GL context 1, let GrDirectContext 1 know its internal
kkinnunen59319222015-11-22 23:23:53 -0800135 // state is invalid.
136 context1->resetContext();
137
138 ///////////////////////////////// CONTEXT 0 ///////////////////////////////////
139
140 // Make a new texture ID in GL Context 0 from the EGL Image
141 glCtx0->makeCurrent();
142 externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL;
143 externalTexture.fID = glCtx0->eglImageToExternalTexture(image);
Greg Daniel2b5be0a2019-06-13 16:50:49 -0400144 externalTexture.fFormat = GR_GL_RGBA8;
Robert Phillipsfee2b4e2017-06-08 18:22:53 -0400145 if (0 == externalTexture.fID) {
146 ERRORF(reporter, "Error converting EGL Image back to texture");
Brian Salomon72050802020-10-12 20:45:06 -0400147 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
Robert Phillipsfee2b4e2017-06-08 18:22:53 -0400148 return;
149 }
kkinnunen59319222015-11-22 23:23:53 -0800150
151 // Wrap this texture ID in a GrTexture
Brian Salomon7e67dca2020-07-21 09:27:25 -0400152 GrBackendTexture backendTex(kSize, kSize, GrMipmapped::kNo, externalTexture);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500153
Brian Salomon14f99fc2020-12-07 12:19:47 -0500154 GrColorInfo colorInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType, nullptr);
Greg Daniel7ef28f32017-04-20 16:41:55 +0000155 // TODO: If I make this TopLeft origin to match resolve_origin calls for kDefault, this test
156 // fails on the Nexus5. Why?
Greg Danielbfa19c42019-12-19 16:41:40 -0500157 GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin;
158 sk_sp<GrSurfaceProxy> texProxy = context0->priv().proxyProvider()->wrapBackendTexture(
Brian Salomon8a78e9c2020-03-27 10:42:15 -0400159 backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
Greg Danielbfa19c42019-12-19 16:41:40 -0500160 if (!texProxy) {
161 ERRORF(reporter, "Error wrapping external texture in GrTextureProxy.");
Brian Salomon72050802020-10-12 20:45:06 -0400162 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
Greg Danielbfa19c42019-12-19 16:41:40 -0500163 return;
164 }
Brian Salomon14f99fc2020-12-07 12:19:47 -0500165 GrSwizzle swizzle = context0->priv().caps()->getReadSwizzle(texProxy->backendFormat(),
166 colorInfo.colorType());
Greg Danield2ccbb52020-02-05 10:45:39 -0500167 GrSurfaceProxyView view(std::move(texProxy), origin, swizzle);
Robert Phillips33bf2b52021-08-02 11:14:38 -0400168 auto surfaceContext = context0->priv().makeSC(std::move(view), colorInfo);
Robert Phillipsd46697a2017-01-25 12:10:37 -0500169
Robert Phillips26caf892017-01-27 10:58:31 -0500170 if (!surfaceContext) {
171 ERRORF(reporter, "Error wrapping external texture in GrSurfaceContext.");
Brian Salomon72050802020-10-12 20:45:06 -0400172 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
Robert Phillips26caf892017-01-27 10:58:31 -0500173 return;
kkinnunen59319222015-11-22 23:23:53 -0800174 }
175
Robert Phillipsabf7b762018-03-21 12:13:37 -0400176 GrTextureProxy* proxy = surfaceContext->asTextureProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -0400177 REPORTER_ASSERT(reporter, proxy->mipmapped() == GrMipmapped::kNo);
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400178 REPORTER_ASSERT(reporter, proxy->peekTexture()->mipmapped() == GrMipmapped::kNo);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400179
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400180 REPORTER_ASSERT(reporter, proxy->textureType() == GrTextureType::kExternal);
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400181 REPORTER_ASSERT(reporter, proxy->peekTexture()->textureType() == GrTextureType::kExternal);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400182 REPORTER_ASSERT(reporter, proxy->hasRestrictedSampling());
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400183 REPORTER_ASSERT(reporter, proxy->peekTexture()->hasRestrictedSampling());
Robert Phillipsabf7b762018-03-21 12:13:37 -0400184
bsalomona98419b2015-11-23 07:09:50 -0800185 // Should not be able to wrap as a RT
Robert Phillipsd46697a2017-01-25 12:10:37 -0500186 {
Robert Phillips33bf2b52021-08-02 11:14:38 -0400187 auto temp = context0->priv().makeSFCFromBackendTexture(colorInfo,
188 backendTex,
189 1,
190 origin,
191 /*release helper*/ nullptr);
Robert Phillips26caf892017-01-27 10:58:31 -0500192 if (temp) {
Robert Phillipsd46697a2017-01-25 12:10:37 -0500193 ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT.");
194 }
kkinnunen59319222015-11-22 23:23:53 -0800195 }
bsalomona98419b2015-11-23 07:09:50 -0800196
Brian Salomonbe1084b2021-01-26 13:29:30 -0500197 //TestReadPixels(reporter, context0, surfaceContext.get(), pixels.get(), "EGLImageTest-read");
bsalomona98419b2015-11-23 07:09:50 -0800198
John Stiles7bf79992021-06-25 11:05:20 -0400199 SkDebugf("type: %d\n", (int)surfaceContext->asTextureProxy()->textureType());
Adlai Hollerc95b5892020-08-11 12:02:22 -0400200 // We should not be able to write to an EXTERNAL texture
201 TestWritePixels(reporter, context0, surfaceContext.get(), false, "EGLImageTest-write");
bsalomona98419b2015-11-23 07:09:50 -0800202
Robert Phillips3500b772017-01-27 10:11:42 -0500203 // Only test RT-config
204 // TODO: why do we always need to draw to copy from an external texture?
Brian Salomon14f99fc2020-12-07 12:19:47 -0500205 TestCopyFromSurface(reporter,
206 context0,
Brian Salomon982127b2021-01-21 10:43:35 -0500207 surfaceContext->asSurfaceProxyRef(),
Brian Salomon14f99fc2020-12-07 12:19:47 -0500208 surfaceContext->origin(),
209 colorInfo.colorType(),
210 pixels.get(),
211 "EGLImageTest-copy");
bsalomona98419b2015-11-23 07:09:50 -0800212
Brian Salomon72050802020-10-12 20:45:06 -0400213 cleanup(glCtx0, externalTexture.fID, glCtx1.get(), context1, image);
bsalomon7ea33f52015-11-22 14:51:00 -0800214}
John Rosascoa9b348f2019-11-08 13:18:15 -0800215
216#endif // SK_GL