Path: blob/main_old/src/tests/egl_tests/EGLStreamTest.cpp
1693 views
//1// Copyright 2016 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// EGLStreamTest:6// Tests pertaining to egl::Stream.7//89#include <gtest/gtest.h>1011#include <vector>1213#include "media/yuvtest.inl"14#include "test_utils/ANGLETest.h"15#include "test_utils/gl_raii.h"16#include "util/EGLWindow.h"17#include "util/OSWindow.h"1819using namespace angle;2021namespace22{2324bool CheckTextureSupport(ID3D11Device *device, DXGI_FORMAT format)25{26HRESULT result;27UINT formatSupport;28result = device->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);29if (result == E_FAIL)30{31return false;32}33return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;34}3536bool CheckNV12TextureSupport(ID3D11Device *device)37{38return CheckTextureSupport(device, DXGI_FORMAT_NV12);39}4041bool CheckP010TextureSupport(ID3D11Device *device)42{43return CheckTextureSupport(device, DXGI_FORMAT_P010);44}4546class EGLStreamTest : public ANGLETest47{48protected:49EGLStreamTest()50{51setWindowWidth(128);52setWindowHeight(128);53setConfigRedBits(8);54setConfigGreenBits(8);55setConfigBlueBits(8);56setConfigAlphaBits(8);57setConfigDepthBits(24);58}59};6061// Tests validation of the stream API62TEST_P(EGLStreamTest, StreamValidationTest)63{64EGLWindow *window = getEGLWindow();65EGLDisplay display = window->getDisplay();66const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);67if (strstr(extensionsString, "EGL_KHR_stream") == nullptr)68{69std::cout << "Stream extension not supported" << std::endl;70return;71}7273const EGLint streamAttributesBad[] = {74EGL_STREAM_STATE_KHR,750,76EGL_NONE,77EGL_PRODUCER_FRAME_KHR,780,79EGL_NONE,80EGL_CONSUMER_FRAME_KHR,810,82EGL_NONE,83EGL_CONSUMER_LATENCY_USEC_KHR,84-1,85EGL_NONE,86EGL_RED_SIZE,87EGL_DONT_CARE,88EGL_NONE,89};9091// Validate create stream attributes92EGLStreamKHR stream = eglCreateStreamKHR(display, &streamAttributesBad[0]);93ASSERT_EGL_ERROR(EGL_BAD_ACCESS);94ASSERT_EQ(EGL_NO_STREAM_KHR, stream);9596stream = eglCreateStreamKHR(display, &streamAttributesBad[3]);97ASSERT_EGL_ERROR(EGL_BAD_ACCESS);98ASSERT_EQ(EGL_NO_STREAM_KHR, stream);99100stream = eglCreateStreamKHR(display, &streamAttributesBad[6]);101ASSERT_EGL_ERROR(EGL_BAD_ACCESS);102ASSERT_EQ(EGL_NO_STREAM_KHR, stream);103104stream = eglCreateStreamKHR(display, &streamAttributesBad[9]);105ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);106ASSERT_EQ(EGL_NO_STREAM_KHR, stream);107108stream = eglCreateStreamKHR(display, &streamAttributesBad[12]);109ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);110ASSERT_EQ(EGL_NO_STREAM_KHR, stream);111112const EGLint streamAttributes[] = {113EGL_CONSUMER_LATENCY_USEC_KHR,1140,115EGL_NONE,116};117118stream = eglCreateStreamKHR(EGL_NO_DISPLAY, streamAttributes);119ASSERT_EGL_ERROR(EGL_BAD_DISPLAY);120ASSERT_EQ(EGL_NO_STREAM_KHR, stream);121122// Create an actual stream123stream = eglCreateStreamKHR(display, streamAttributes);124ASSERT_EGL_SUCCESS();125ASSERT_NE(EGL_NO_STREAM_KHR, stream);126127// Assert it is in the created state128EGLint state;129eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);130ASSERT_EGL_SUCCESS();131ASSERT_EQ(EGL_STREAM_STATE_CREATED_KHR, state);132133// Test getting and setting the latency134EGLint latency = 10;135eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, latency);136ASSERT_EGL_SUCCESS();137eglQueryStreamKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, &latency);138ASSERT_EGL_SUCCESS();139ASSERT_EQ(10, latency);140eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, -1);141ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);142ASSERT_EQ(10, latency);143144// Test the 64-bit queries145EGLuint64KHR value;146eglQueryStreamu64KHR(display, stream, EGL_CONSUMER_FRAME_KHR, &value);147ASSERT_EGL_SUCCESS();148eglQueryStreamu64KHR(display, stream, EGL_PRODUCER_FRAME_KHR, &value);149ASSERT_EGL_SUCCESS();150151// Destroy the stream152eglDestroyStreamKHR(display, stream);153ASSERT_EGL_SUCCESS();154}155156// Tests validation of stream consumer gltexture API157TEST_P(EGLStreamTest, StreamConsumerGLTextureValidationTest)158{159EGLWindow *window = getEGLWindow();160EGLDisplay display = window->getDisplay();161const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);162if (strstr(extensionsString, "EGL_KHR_stream_consumer_gltexture") == nullptr)163{164std::cout << "Stream consumer gltexture extension not supported" << std::endl;165return;166}167168const EGLint streamAttributes[] = {169EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,170};171172EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);173ASSERT_EGL_SUCCESS();174175EGLBoolean result = eglStreamConsumerGLTextureExternalKHR(display, stream);176ASSERT_EGL_FALSE(result);177ASSERT_EGL_ERROR(EGL_BAD_ACCESS);178179GLTexture tex;180glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);181result = eglStreamConsumerGLTextureExternalKHR(display, stream);182ASSERT_EGL_TRUE(result);183ASSERT_EGL_SUCCESS();184185EGLint state;186eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);187ASSERT_EGL_SUCCESS();188ASSERT_EQ(EGL_STREAM_STATE_CONNECTING_KHR, state);189190eglDestroyStreamKHR(display, stream);191ASSERT_EGL_SUCCESS();192}193194// Tests validation of stream consumer gltexture yuv API195TEST_P(EGLStreamTest, StreamConsumerGLTextureYUVValidationTest)196{197EGLWindow *window = getEGLWindow();198EGLDisplay display = window->getDisplay();199const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);200if (strstr(extensionsString, "EGL_NV_stream_consumer_gltexture_yuv") == nullptr)201{202std::cout << "Stream consumer gltexture yuv extension not supported" << std::endl;203return;204}205206const EGLint streamAttributes[] = {207EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,208};209210EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);211ASSERT_EGL_SUCCESS();212213EGLAttrib consumerAttributesBad[] = {214EGL_COLOR_BUFFER_TYPE,215EGL_YUV_BUFFER_EXT, // 0216EGL_YUV_NUMBER_OF_PLANES_EXT,2170,218EGL_NONE,219EGL_COLOR_BUFFER_TYPE,220EGL_YUV_BUFFER_EXT, // 5221EGL_YUV_NUMBER_OF_PLANES_EXT,2221,223EGL_NONE,224EGL_COLOR_BUFFER_TYPE,225EGL_YUV_BUFFER_EXT, // 10226EGL_YUV_NUMBER_OF_PLANES_EXT,2271,228EGL_YUV_PLANE0_TEXTURE_UNIT_NV,2299999,230EGL_NONE,231EGL_COLOR_BUFFER_TYPE,232EGL_YUV_BUFFER_EXT, // 17233EGL_YUV_NUMBER_OF_PLANES_EXT,2341,235EGL_YUV_PLANE0_TEXTURE_UNIT_NV,2360,237EGL_YUV_PLANE1_TEXTURE_UNIT_NV,2381,239EGL_NONE,240EGL_COLOR_BUFFER_TYPE,241EGL_YUV_BUFFER_EXT, // 26242EGL_YUV_NUMBER_OF_PLANES_EXT,2432,244EGL_YUV_PLANE0_TEXTURE_UNIT_NV,2450,246EGL_YUV_PLANE1_TEXTURE_UNIT_NV,2470,248EGL_NONE,249};250251EGLAttrib consumerAttributes[] = {252EGL_COLOR_BUFFER_TYPE,253EGL_YUV_BUFFER_EXT,254EGL_YUV_NUMBER_OF_PLANES_EXT,2552,256EGL_YUV_PLANE0_TEXTURE_UNIT_NV,2570,258EGL_YUV_PLANE1_TEXTURE_UNIT_NV,2591,260EGL_NONE,261};262263EGLBoolean result =264eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[0]);265ASSERT_EGL_FALSE(result);266ASSERT_EGL_ERROR(EGL_BAD_MATCH);267268result =269eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[5]);270ASSERT_EGL_FALSE(result);271ASSERT_EGL_ERROR(EGL_BAD_MATCH);272273result =274eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[10]);275ASSERT_EGL_FALSE(result);276ASSERT_EGL_ERROR(EGL_BAD_ACCESS);277278result =279eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[17]);280ASSERT_EGL_FALSE(result);281ASSERT_EGL_ERROR(EGL_BAD_MATCH);282283result = eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);284ASSERT_EGL_FALSE(result);285ASSERT_EGL_ERROR(EGL_BAD_ACCESS);286287GLTexture tex[2];288glActiveTexture(GL_TEXTURE0);289glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);290glActiveTexture(GL_TEXTURE1);291glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);292293result =294eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[26]);295ASSERT_EGL_FALSE(result);296ASSERT_EGL_ERROR(EGL_BAD_ACCESS);297298result = eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);299ASSERT_EGL_TRUE(result);300ASSERT_EGL_SUCCESS();301302EGLint state;303eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);304ASSERT_EGL_SUCCESS();305ASSERT_EQ(EGL_STREAM_STATE_CONNECTING_KHR, state);306307eglDestroyStreamKHR(display, stream);308ASSERT_EGL_SUCCESS();309}310311// Tests that deleting a texture invalidates the associated stream312TEST_P(EGLStreamTest, StreamConsumerGLTextureYUVDeletionTest)313{314EGLWindow *window = getEGLWindow();315EGLDisplay display = window->getDisplay();316const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);317if (strstr(extensionsString, "EGL_ANGLE_stream_producer_d3d_texture") == nullptr)318{319std::cout << "Stream producer d3d texture not supported" << std::endl;320return;321}322323const EGLint streamAttributes[] = {324EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,325};326327EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);328ASSERT_EGL_SUCCESS();329330EGLAttrib consumerAttributes[] = {331EGL_COLOR_BUFFER_TYPE,332EGL_YUV_BUFFER_EXT,333EGL_YUV_NUMBER_OF_PLANES_EXT,3342,335EGL_YUV_PLANE0_TEXTURE_UNIT_NV,3360,337EGL_YUV_PLANE1_TEXTURE_UNIT_NV,3381,339EGL_NONE,340};341342// Note: The purpose of this test means that we can't use the RAII GLTexture class343GLuint tex[2];344glGenTextures(2, tex);345glActiveTexture(GL_TEXTURE0);346glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);347glActiveTexture(GL_TEXTURE1);348glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);349350EGLBoolean result =351eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);352ASSERT_EGL_TRUE(result);353ASSERT_EGL_SUCCESS();354355EGLAttrib producerAttributes[] = {356EGL_NONE,357};358359result = eglCreateStreamProducerD3DTextureANGLE(display, stream, producerAttributes);360ASSERT_EGL_TRUE(result);361ASSERT_EGL_SUCCESS();362363EGLint state;364eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);365ASSERT_EGL_SUCCESS();366ASSERT_EQ(EGL_STREAM_STATE_EMPTY_KHR, state);367368// Delete the first texture, which should be enough to invalidate the stream369glDeleteTextures(1, tex);370371eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);372ASSERT_EGL_SUCCESS();373ASSERT_EQ(EGL_STREAM_STATE_DISCONNECTED_KHR, state);374375eglDestroyStreamKHR(display, stream);376ASSERT_EGL_SUCCESS();377}378379class D3D11TextureStreamSamplingTest : public ANGLETest380{381protected:382void testSetUp() override383{384EGLWindow *window = getEGLWindow();385mDisplay = window->getDisplay();386if (!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_stream_producer_d3d_texture"))387{388std::cout << "Stream producer d3d texture not supported" << std::endl;389return;390}391392glGenRenderbuffers(1, &mRB);393glBindRenderbuffer(GL_RENDERBUFFER, mRB);394glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 2, 2);395glBindRenderbuffer(GL_RENDERBUFFER, 0);396397glGenFramebuffers(1, &mFB);398glBindFramebuffer(GL_FRAMEBUFFER, mFB);399glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRB);400ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);401402glViewport(0, 0, 2, 2);403glClearColor(1, 0, 0, 1);404glClear(GL_COLOR_BUFFER_BIT);405ASSERT_GL_NO_ERROR();406407uint32_t pixel;408glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);409ASSERT_EQ(pixel, 0xff0000ff);410411mStream = eglCreateStreamKHR(mDisplay, nullptr);412ASSERT_EGL_SUCCESS();413414EGLDeviceEXT eglDevice;415eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, (EGLAttrib *)&eglDevice);416eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, (EGLAttrib *)&mD3D);417}418419void testTearDown() override420{421EGLBoolean result = eglDestroyStreamKHR(mDisplay, mStream);422ASSERT_EGL_TRUE(result);423ASSERT_EGL_SUCCESS();424425glDeleteRenderbuffers(1, &mRB);426glDeleteFramebuffers(1, &mFB);427}428429EGLDisplay mDisplay = 0;430EGLStreamKHR mStream = 0;431GLuint mRB = 0;432GLuint mFB = 0;433ID3D11Device *mD3D;434};435436// Test RGBA texture sampling via EGLStreams437TEST_P(D3D11TextureStreamSamplingTest, RGBA)438{439EGLWindow *window = getEGLWindow();440EGLDisplay display = window->getDisplay();441ANGLE_SKIP_TEST_IF(442!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));443444constexpr char kVertShader[] = R"(445attribute vec4 aPos;446varying vec2 vTexCoord;447void main()448{449gl_Position = aPos;450vTexCoord = gl_Position.xy * 0.5 + 0.5;451}452)";453constexpr char kFragShader[] = R"(454#extension GL_NV_EGL_stream_consumer_external : require455precision mediump float;456uniform samplerExternalOES uTex;457varying vec2 vTexCoord;458void main()459{460gl_FragColor = texture2D(uTex, vTexCoord);461}462)";463ANGLE_GL_PROGRAM(prog, kVertShader, kFragShader);464glUseProgram(prog);465glUniform1i(glGetUniformLocation(prog, "uTex"), 0);466467GLTexture tex;468glActiveTexture(GL_TEXTURE0);469glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);470glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);471ASSERT_GL_NO_ERROR();472473EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(mDisplay, mStream, nullptr);474ASSERT_EGL_TRUE(result);475ASSERT_EGL_SUCCESS();476glActiveTexture(GL_TEXTURE3); // Set to an unused slot to ensure StreamConsumer picked up477// the current slot.478479result = eglCreateStreamProducerD3DTextureANGLE(mDisplay, mStream, nullptr);480ASSERT_EGL_TRUE(result);481ASSERT_EGL_SUCCESS();482483// Create and post the d3d11 texture484485D3D11_TEXTURE2D_DESC desc = {};486desc.Width = 1;487desc.Height = 1;488desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;489desc.MipLevels = 1;490desc.ArraySize = 1;491desc.SampleDesc.Count = 1;492desc.Usage = D3D11_USAGE_DEFAULT;493desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;494495constexpr uint8_t texData[] = {0x10, 0x20, 0x30, 0x40};496D3D11_SUBRESOURCE_DATA subres;497subres.pSysMem = texData;498subres.SysMemPitch = 4;499500ID3D11Texture2D *texture = nullptr;501(void)mD3D->CreateTexture2D(&desc, &subres, &texture);502ASSERT_NE(nullptr, texture);503504result = eglStreamPostD3DTextureANGLE(mDisplay, mStream, (void *)texture, nullptr);505ASSERT_EGL_TRUE(result);506ASSERT_EGL_SUCCESS();507508// Sample and test509510result = eglStreamConsumerAcquireKHR(mDisplay, mStream);511ASSERT_EGL_TRUE(result);512ASSERT_EGL_SUCCESS();513514drawQuad(prog, "aPos", 0.0);515516uint32_t pixel;517glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);518ASSERT_GL_NO_ERROR();519ASSERT_EQ(pixel, static_cast<uint32_t>(0x40302010));520521result = eglStreamConsumerReleaseKHR(mDisplay, mStream);522ASSERT_EGL_TRUE(result);523ASSERT_EGL_SUCCESS();524}525526// Test NV12 texture sampling via EGLStreams527TEST_P(D3D11TextureStreamSamplingTest, NV12)528{529EGLWindow *window = getEGLWindow();530EGLDisplay display = window->getDisplay();531ANGLE_SKIP_TEST_IF(532!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));533ANGLE_SKIP_TEST_IF(!CheckNV12TextureSupport(mD3D));534535constexpr char kVertShader[] = R"(536attribute vec4 aPos;537varying vec2 vTexCoord;538void main()539{540gl_Position = aPos;541vTexCoord = gl_Position.xy * 0.5 + 0.5;542}543)";544const char kFragShader[] = R"(545#extension GL_NV_EGL_stream_consumer_external : require546precision mediump float;547uniform samplerExternalOES uTexY;548uniform samplerExternalOES uTexUV;549varying vec2 vTexCoord;550void main()551{552gl_FragColor.r = texture2D(uTexY, vTexCoord).r;553gl_FragColor.gb = texture2D(uTexUV, vTexCoord).rg;554gl_FragColor.a = 1.0;555}556)";557ANGLE_GL_PROGRAM(prog, kVertShader, kFragShader);558glUseProgram(prog);559glUniform1i(glGetUniformLocation(prog, "uTexY"), 0);560glUniform1i(glGetUniformLocation(prog, "uTexUV"), 1);561562ASSERT_GL_NO_ERROR();563564GLTexture tex[2];565glActiveTexture(GL_TEXTURE0);566glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);567glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);568ASSERT_GL_NO_ERROR();569glActiveTexture(GL_TEXTURE1);570glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);571glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);572ASSERT_GL_NO_ERROR();573574glActiveTexture(GL_TEXTURE3); // Set to an unused slot to ensure StreamConsumer picks up575// the current slot.576constexpr EGLAttrib consumerAttributes[] = {577EGL_COLOR_BUFFER_TYPE,578EGL_YUV_BUFFER_EXT,579EGL_YUV_NUMBER_OF_PLANES_EXT,5802,581EGL_YUV_PLANE0_TEXTURE_UNIT_NV,5820,583EGL_YUV_PLANE1_TEXTURE_UNIT_NV,5841,585EGL_NONE,586};587EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(588mDisplay, mStream, const_cast<EGLAttrib *>(consumerAttributes));589ASSERT_EGL_TRUE(result);590ASSERT_EGL_SUCCESS();591592result = eglCreateStreamProducerD3DTextureANGLE(mDisplay, mStream, nullptr);593ASSERT_EGL_TRUE(result);594ASSERT_EGL_SUCCESS();595596// Create and post the d3d11 texture597598D3D11_TEXTURE2D_DESC desc = {};599desc.Width = 2;600desc.Height = 2;601desc.Format = DXGI_FORMAT_NV12;602desc.MipLevels = 1;603desc.ArraySize = 1;604desc.SampleDesc.Count = 1;605desc.Usage = D3D11_USAGE_DEFAULT;606desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;607608/* DXGI_FORMAT_NV12:609* Width and height must be even.610* Direct3D 11 staging resources and initData parameters for this format use611* (rowPitch * (height + (height / 2))) bytes.612* The first (SysMemPitch * height) bytes are the Y plane, the remaining613* (SysMemPitch * (height / 2)) bytes are the UV plane.614*/615constexpr uint8_t texData[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60};616D3D11_SUBRESOURCE_DATA subres;617subres.pSysMem = texData;618subres.SysMemPitch = 2;619620ID3D11Texture2D *texture = nullptr;621(void)mD3D->CreateTexture2D(&desc, &subres, &texture);622ASSERT_NE(nullptr, texture);623624result = eglStreamPostD3DTextureANGLE(mDisplay, mStream, (void *)texture, nullptr);625ASSERT_EGL_TRUE(result);626ASSERT_EGL_SUCCESS();627628// Sample and test629630result = eglStreamConsumerAcquireKHR(mDisplay, mStream);631ASSERT_EGL_TRUE(result);632ASSERT_EGL_SUCCESS();633634drawQuad(prog, "aPos", 0.0);635uint32_t pixel;636glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);637ASSERT_EQ(pixel, 0xff605010);638639glReadPixels(1, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);640ASSERT_EQ(pixel, 0xff605020);641642glReadPixels(0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);643ASSERT_EQ(pixel, 0xff605030);644645glReadPixels(1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);646ASSERT_EQ(pixel, 0xff605040);647648result = eglStreamConsumerReleaseKHR(mDisplay, mStream);649ASSERT_EGL_TRUE(result);650ASSERT_EGL_SUCCESS();651}652653// End2end test for rendering an NV12 texture. Renders a YUV quad, reads back the RGB values, and654// ensures they are correct655TEST_P(EGLStreamTest, StreamProducerTextureNV12End2End)656{657EGLWindow *window = getEGLWindow();658EGLDisplay display = window->getDisplay();659ANGLE_SKIP_TEST_IF(660!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));661662bool useESSL3Shaders =663getClientMajorVersion() >= 3 && IsGLExtensionEnabled("GL_OES_EGL_image_external_essl3");664665// yuv to rgb conversion shader using Microsoft's given conversion formulas666const char *yuvVS = nullptr;667const char *yuvPS = nullptr;668if (useESSL3Shaders)669{670yuvVS =671"#version 300 es\n"672"in highp vec4 position;\n"673"out vec2 texcoord;\n"674"void main(void)\n"675"{\n"676" gl_Position = position;\n"677" texcoord = (position.xy * 0.5) + 0.5;\n"678" texcoord.y = 1.0 - texcoord.y;\n"679"}\n";680yuvPS =681"#version 300 es\n"682"#extension GL_OES_EGL_image_external_essl3 : require\n"683"#extension GL_NV_EGL_stream_consumer_external : require\n"684"precision highp float;\n"685"in vec2 texcoord;\n"686"out vec4 color;\n"687"uniform samplerExternalOES y;\n"688"uniform samplerExternalOES uv\n;"689"void main(void)\n"690"{\n"691" float c = texture(y, texcoord).r - (16.0 / 256.0);\n"692" float d = texture(uv, texcoord).r - 0.5;\n"693" float e = texture(uv, texcoord).g - 0.5;\n"694" float r = 1.164383 * c + 1.596027 * e;\n"695" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"696" float b = 1.164383 * c + 2.017232 * d;\n"697" color = vec4(r, g, b, 1.0);\n"698"}\n";699}700else701{702yuvVS =703"attribute highp vec4 position;\n"704"varying vec2 texcoord;\n"705"void main(void)\n"706"{\n"707" gl_Position = position;\n"708" texcoord = (position.xy * 0.5) + 0.5;\n"709" texcoord.y = 1.0 - texcoord.y;\n"710"}\n";711712yuvPS =713"#extension GL_NV_EGL_stream_consumer_external : require\n"714"precision highp float;\n"715"varying vec2 texcoord;\n"716"uniform samplerExternalOES y;\n"717"uniform samplerExternalOES uv\n;"718"void main(void)\n"719"{\n"720" float c = texture2D(y, texcoord).r - (16.0 / 256.0);\n"721" float d = texture2D(uv, texcoord).r - 0.5;\n"722" float e = texture2D(uv, texcoord).g - 0.5;\n"723" float r = 1.164383 * c + 1.596027 * e;\n"724" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"725" float b = 1.164383 * c + 2.017232 * d;\n"726" gl_FragColor = vec4(r, g, b, 1.0);\n"727"}\n";728}729730ANGLE_GL_PROGRAM(program, yuvVS, yuvPS);731GLuint yUniform = glGetUniformLocation(program, "y");732GLuint uvUniform = glGetUniformLocation(program, "uv");733734// Fetch the D3D11 device735EGLDeviceEXT eglDevice;736eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, (EGLAttrib *)&eglDevice);737ID3D11Device *device;738eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, (EGLAttrib *)&device);739740ANGLE_SKIP_TEST_IF(!CheckNV12TextureSupport(device));741742// Create the NV12 D3D11 texture743D3D11_TEXTURE2D_DESC desc;744desc.Width = yuvtest_width;745desc.Height = yuvtest_height;746desc.Format = DXGI_FORMAT_NV12;747desc.MipLevels = 1;748desc.ArraySize = 1;749desc.SampleDesc.Count = 1;750desc.SampleDesc.Quality = 0;751desc.Usage = D3D11_USAGE_DEFAULT;752desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;753desc.CPUAccessFlags = 0;754desc.MiscFlags = 0;755756D3D11_SUBRESOURCE_DATA subres;757subres.pSysMem = yuvtest_data;758subres.SysMemPitch = yuvtest_width;759subres.SysMemSlicePitch = yuvtest_width * yuvtest_height * 3 / 2;760761ID3D11Texture2D *texture = nullptr;762(void)device->CreateTexture2D(&desc, &subres, &texture);763ASSERT_NE(nullptr, texture);764765// Create the stream766const EGLint streamAttributes[] = {767EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,768};769770EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);771ASSERT_EGL_SUCCESS();772773EGLAttrib consumerAttributes[] = {774EGL_COLOR_BUFFER_TYPE,775EGL_YUV_BUFFER_EXT,776EGL_YUV_NUMBER_OF_PLANES_EXT,7772,778EGL_YUV_PLANE0_TEXTURE_UNIT_NV,7790,780EGL_YUV_PLANE1_TEXTURE_UNIT_NV,7811,782EGL_NONE,783};784785GLTexture tex[2];786glActiveTexture(GL_TEXTURE0);787glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);788glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);789ASSERT_GL_NO_ERROR();790glActiveTexture(GL_TEXTURE1);791glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);792glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);793ASSERT_GL_NO_ERROR();794795EGLBoolean result =796eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);797ASSERT_EGL_TRUE(result);798ASSERT_EGL_SUCCESS();799800EGLAttrib producerAttributes[] = {801EGL_NONE,802};803804result = eglCreateStreamProducerD3DTextureANGLE(display, stream, producerAttributes);805ASSERT_EGL_TRUE(result);806ASSERT_EGL_SUCCESS();807808// Insert the frame809EGLAttrib frameAttributes[] = {810EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,8110,812EGL_NONE,813};814result = eglStreamPostD3DTextureANGLE(display, stream, (void *)texture, frameAttributes);815ASSERT_EGL_TRUE(result);816ASSERT_EGL_SUCCESS();817818EGLint state;819eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);820ASSERT_EGL_SUCCESS();821ASSERT_EQ(EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR, state);822823eglStreamConsumerAcquireKHR(display, stream);824ASSERT_EGL_SUCCESS();825826glUseProgram(program);827glUniform1i(yUniform, 0);828glUniform1i(uvUniform, 1);829drawQuad(program, "position", 0.0f);830ASSERT_GL_NO_ERROR();831832eglStreamConsumerReleaseKHR(display, stream);833ASSERT_EGL_SUCCESS();834835eglSwapBuffers(display, window->getSurface());836SafeRelease(texture);837}838839// Test P010 texture sampling via EGLStreams840TEST_P(D3D11TextureStreamSamplingTest, P010)841{842EGLWindow *window = getEGLWindow();843EGLDisplay display = window->getDisplay();844ANGLE_SKIP_TEST_IF(845!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));846ANGLE_SKIP_TEST_IF(!CheckP010TextureSupport(mD3D));847ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());848849constexpr char kVertShader[] = R"(850attribute vec4 aPos;851varying vec2 vTexCoord;852void main()853{854gl_Position = aPos;855vTexCoord = gl_Position.xy * 0.5 + 0.5;856})";857858const char kFragShader[] = R"(859#extension GL_NV_EGL_stream_consumer_external : require860precision mediump float;861uniform samplerExternalOES uTexY;862uniform samplerExternalOES uTexUV;863varying vec2 vTexCoord;864void main()865{866gl_FragColor.r = texture2D(uTexY, vTexCoord).r;867gl_FragColor.gb = texture2D(uTexUV, vTexCoord).rg;868gl_FragColor.a = 1.0;869})";870871ANGLE_GL_PROGRAM(prog, kVertShader, kFragShader);872glUseProgram(prog);873GLint location = glGetUniformLocation(prog, "uTexY");874ASSERT_NE(location, -1);875glUniform1i(location, 0);876location = glGetUniformLocation(prog, "uTexUV");877ASSERT_NE(location, -1);878glUniform1i(location, 1);879880ASSERT_GL_NO_ERROR();881882GLTexture tex[2];883glActiveTexture(GL_TEXTURE0);884glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);885glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);886ASSERT_GL_NO_ERROR();887glActiveTexture(GL_TEXTURE1);888glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);889glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);890ASSERT_GL_NO_ERROR();891892glActiveTexture(GL_TEXTURE3); // Set to an unused slot to ensure StreamConsumer picks up893// the current slot.894constexpr EGLAttrib consumerAttributes[] = {895EGL_COLOR_BUFFER_TYPE,896EGL_YUV_BUFFER_EXT,897EGL_YUV_NUMBER_OF_PLANES_EXT,8982,899EGL_YUV_PLANE0_TEXTURE_UNIT_NV,9000,901EGL_YUV_PLANE1_TEXTURE_UNIT_NV,9021,903EGL_NONE,904};905EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(906mDisplay, mStream, const_cast<EGLAttrib *>(consumerAttributes));907ASSERT_EGL_TRUE(result);908ASSERT_EGL_SUCCESS();909910result = eglCreateStreamProducerD3DTextureANGLE(mDisplay, mStream, nullptr);911ASSERT_EGL_TRUE(result);912ASSERT_EGL_SUCCESS();913914// Create and post the d3d11 texture915916D3D11_TEXTURE2D_DESC desc = {};917desc.Width = 2;918desc.Height = 2;919desc.Format = DXGI_FORMAT_P010;920desc.MipLevels = 1;921desc.ArraySize = 1;922desc.SampleDesc.Count = 1;923desc.Usage = D3D11_USAGE_DEFAULT;924desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;925926// DXGI_FORMAT_P010:927// Width and height must be even.928// Direct3D 11 staging resources and initData parameters for this format use929// (rowPitch * (height + (height / 2))) bytes.930// The first (SysMemPitch * height) bytes are the Y plane, the remaining931// (SysMemPitch * (height / 2)) bytes are the UV plane.932constexpr uint16_t texData[] = {0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000};933D3D11_SUBRESOURCE_DATA subres;934subres.pSysMem = texData;935subres.SysMemPitch = 4;936937ID3D11Texture2D *texture = nullptr;938(void)mD3D->CreateTexture2D(&desc, &subres, &texture);939ASSERT_NE(nullptr, texture);940941result = eglStreamPostD3DTextureANGLE(mDisplay, mStream, (void *)texture, nullptr);942ASSERT_EGL_TRUE(result);943ASSERT_EGL_SUCCESS();944945// Sample and test946947result = eglStreamConsumerAcquireKHR(mDisplay, mStream);948ASSERT_EGL_TRUE(result);949ASSERT_EGL_SUCCESS();950951drawQuad(prog, "aPos", 0.0);952uint32_t pixel;953glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);954ASSERT_EQ(pixel, 0xff605010);955956glReadPixels(1, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);957ASSERT_EQ(pixel, 0xff605020);958959glReadPixels(0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);960ASSERT_EQ(pixel, 0xff605030);961962glReadPixels(1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);963ASSERT_EQ(pixel, 0xff605040);964965result = eglStreamConsumerReleaseKHR(mDisplay, mStream);966ASSERT_EGL_TRUE(result);967ASSERT_EGL_SUCCESS();968}969970ANGLE_INSTANTIATE_TEST(EGLStreamTest,971ES2_D3D9(),972ES2_D3D11(),973ES3_D3D11(),974ES2_OPENGL(),975ES3_OPENGL(),976ES2_VULKAN());977ANGLE_INSTANTIATE_TEST(D3D11TextureStreamSamplingTest, ES2_D3D11(), ES3_D3D11(), ES31_D3D11());978} // anonymous namespace979980981