Path: blob/main_old/src/tests/gl_tests/ClipDistanceTest.cpp
1693 views
//1// Copyright 2020 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// ClipDistanceTest.cpp: Test cases for GL_APPLE_clip_distance/GL_EXT_clip_cull_distance extension.6//78#include "test_utils/ANGLETest.h"9#include "test_utils/gl_raii.h"10#include "util/EGLWindow.h"11#include "util/test_utils.h"1213using namespace angle;1415class ClipDistanceTest : public ANGLETest16{17protected:18ClipDistanceTest()19{20setWindowWidth(16);21setWindowHeight(16);22setConfigRedBits(8);23setConfigGreenBits(8);24setConfigBlueBits(8);25setConfigAlphaBits(8);26setConfigDepthBits(24);27}28};2930// Query max clip distances and enable, disable states of clip distances31TEST_P(ClipDistanceTest, StateQuery)32{33ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));3435GLint maxClipDistances = 0;36glGetIntegerv(GL_MAX_CLIP_DISTANCES_APPLE, &maxClipDistances);3738EXPECT_GL_NO_ERROR();39EXPECT_GE(maxClipDistances, 8);4041GLboolean enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);42EXPECT_GL_NO_ERROR();43EXPECT_EQ(enabled, GL_FALSE);4445glEnable(GL_CLIP_DISTANCE1_APPLE);46EXPECT_GL_NO_ERROR();47glEnable(GL_CLIP_DISTANCE7_APPLE);48EXPECT_GL_NO_ERROR();49enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);50EXPECT_EQ(enabled, GL_TRUE);5152glDisable(GL_CLIP_DISTANCE1_APPLE);53EXPECT_GL_NO_ERROR();54enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);55EXPECT_EQ(enabled, GL_FALSE);5657EXPECT_EQ(glIsEnabled(GL_CLIP_DISTANCE7_APPLE), GL_TRUE);58}5960// Write to one gl_ClipDistance element61TEST_P(ClipDistanceTest, OneClipDistance)62{63ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));6465constexpr char kVS[] = R"(66#extension GL_APPLE_clip_distance : require6768uniform vec4 u_plane;6970attribute vec2 a_position;7172void main()73{74gl_Position = vec4(a_position, 0.0, 1.0);7576gl_ClipDistance[0] = dot(gl_Position, u_plane);77})";7879ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());80glLinkProgram(programRed);81glUseProgram(programRed);82ASSERT_GL_NO_ERROR();8384glEnable(GL_CLIP_DISTANCE0_APPLE);8586// Clear to blue87glClearColor(0, 0, 1, 1);88glClear(GL_COLOR_BUFFER_BIT);8990// Draw full screen quad with color red91glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);92EXPECT_GL_NO_ERROR();93drawQuad(programRed, "a_position", 0);94EXPECT_GL_NO_ERROR();9596// All pixels on the left of the plane x = -0.5 must be blue97for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)98{99for (int y = 0; y < getWindowHeight(); ++y)100{101EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);102}103}104105// All pixels on the right of the plane x = -0.5 must be red106for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth(); ++x)107{108for (int y = 0; y < getWindowHeight(); ++y)109{110EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);111}112}113114// Clear to green115glClearColor(0, 1, 0, 1);116glClear(GL_COLOR_BUFFER_BIT);117118// Draw full screen quad with color red119glUniform4f(glGetUniformLocation(programRed, "u_plane"), -1, 0, 0, -0.5);120EXPECT_GL_NO_ERROR();121drawQuad(programRed, "a_position", 0);122EXPECT_GL_NO_ERROR();123124// All pixels on the left of the plane x = -0.5 must be red125for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)126{127for (int y = 0; y < getWindowHeight(); ++y)128{129EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);130}131}132133// All pixels on the right of the plane x = -0.5 must be green134for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth(); ++x)135{136for (int y = 0; y < getWindowHeight(); ++y)137{138EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);139}140}141142// Disable GL_CLIP_DISTANCE143glDisable(GL_CLIP_DISTANCE0_APPLE);144drawQuad(programRed, "a_position", 0);145146// All pixels must be red147for (int x = 0; x < getWindowWidth(); ++x)148{149for (int y = 0; y < getWindowHeight(); ++y)150{151EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);152}153}154}155156// Write to 3 clip distances157TEST_P(ClipDistanceTest, ThreeClipDistances)158{159ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));160161constexpr char kVS[] = R"(162#extension GL_APPLE_clip_distance : require163164uniform vec4 u_plane[3];165166attribute vec2 a_position;167168void main()169{170gl_Position = vec4(a_position, 0.0, 1.0);171172gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);173gl_ClipDistance[3] = dot(gl_Position, u_plane[1]);174gl_ClipDistance[7] = dot(gl_Position, u_plane[2]);175})";176177ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());178glLinkProgram(programRed);179glUseProgram(programRed);180ASSERT_GL_NO_ERROR();181182// Enable 3 clip distances183glEnable(GL_CLIP_DISTANCE0_APPLE);184glEnable(GL_CLIP_DISTANCE3_APPLE);185glEnable(GL_CLIP_DISTANCE7_APPLE);186ASSERT_GL_NO_ERROR();187188// Clear to blue189glClearColor(0, 0, 1, 1);190glClear(GL_COLOR_BUFFER_BIT);191192// Draw full screen quad with color red193// x = -0.5194glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);195// x = 0.5196glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);197// x + y = 1198glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);199EXPECT_GL_NO_ERROR();200drawQuad(programRed, "a_position", 0);201EXPECT_GL_NO_ERROR();202203// All pixels on the left of the plane x = -0.5 must be blue204for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)205{206for (int y = 0; y < getWindowHeight(); ++y)207{208EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);209}210}211212// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right213// triangle214for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)215{216for (int y = 0; y < getWindowHeight(); ++y)217{218EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);219}220}221222for (int y = 0; y < getWindowHeight(); ++y)223{224for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)225{226if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)227{228// bottom left triangle clipped by x=0.5 plane229EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);230}231else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)232{233// upper right triangle plus right of x=0.5 plane234EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);235}236}237}238239// Clear to green240glClearColor(0, 1, 0, 1);241glClear(GL_COLOR_BUFFER_BIT);242243// Disable gl_ClipDistance[3]244glDisable(GL_CLIP_DISTANCE3_APPLE);245246// Draw full screen quad with color red247EXPECT_GL_NO_ERROR();248drawQuad(programRed, "a_position", 0);249EXPECT_GL_NO_ERROR();250251// All pixels on the left of the plane x = -0.5 must be green252for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)253{254for (int y = 0; y < getWindowHeight(); ++y)255{256EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);257}258}259260// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right261// triangle262for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)263{264for (int y = 0; y < getWindowHeight(); ++y)265{266EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);267}268}269270for (int y = 0; y < getWindowHeight(); ++y)271{272for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)273{274if (x < getWindowWidth() * 3 / 2 - y - 1)275{276// bottom left triangle277EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);278}279else if (x > getWindowWidth() * 3 / 2 - y + 1)280{281// upper right triangle282EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);283}284}285}286}287288// Redeclare gl_ClipDistance in shader with explicit size, also use it in a global function289// outside main()290TEST_P(ClipDistanceTest, ThreeClipDistancesRedeclared)291{292ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));293294constexpr char kVS[] = R"(295#extension GL_APPLE_clip_distance : require296297varying highp float gl_ClipDistance[3];298299void computeClipDistances(in vec4 position, in vec4 plane[3])300{301gl_ClipDistance[0] = dot(position, plane[0]);302gl_ClipDistance[1] = dot(position, plane[1]);303gl_ClipDistance[2] = dot(position, plane[2]);304}305306uniform vec4 u_plane[3];307308attribute vec2 a_position;309310void main()311{312gl_Position = vec4(a_position, 0.0, 1.0);313314computeClipDistances(gl_Position, u_plane);315})";316317ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());318glLinkProgram(programRed);319glUseProgram(programRed);320ASSERT_GL_NO_ERROR();321322// Enable 3 clip distances323glEnable(GL_CLIP_DISTANCE0_APPLE);324glEnable(GL_CLIP_DISTANCE1_APPLE);325glEnable(GL_CLIP_DISTANCE2_APPLE);326ASSERT_GL_NO_ERROR();327328// Clear to blue329glClearColor(0, 0, 1, 1);330glClear(GL_COLOR_BUFFER_BIT);331332// Draw full screen quad with color red333// x = -0.5334glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);335// x = 0.5336glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);337// x + y = 1338glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);339EXPECT_GL_NO_ERROR();340drawQuad(programRed, "a_position", 0);341EXPECT_GL_NO_ERROR();342343// All pixels on the left of the plane x = -0.5 must be blue344for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)345{346for (int y = 0; y < getWindowHeight(); ++y)347{348EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);349}350}351352// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right353// triangle354for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)355{356for (int y = 0; y < getWindowHeight(); ++y)357{358EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);359}360}361362for (int y = 0; y < getWindowHeight(); ++y)363{364for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)365{366if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)367{368// bottom left triangle clipped by x=0.5 plane369EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);370}371else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)372{373// upper right triangle plus right of x=0.5 plane374EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);375}376}377}378}379380class ClipCullDistanceTest : public ClipDistanceTest381{};382383// Query max clip distances and enable, disable states of clip distances384TEST_P(ClipCullDistanceTest, StateQuery)385{386ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));387388GLint maxClipDistances = 0;389glGetIntegerv(GL_MAX_CLIP_DISTANCES_EXT, &maxClipDistances);390391EXPECT_GL_NO_ERROR();392EXPECT_GE(maxClipDistances, 8);393394GLint maxCullDistances = 0;395glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances);396397EXPECT_GL_NO_ERROR();398EXPECT_GE(maxCullDistances, 8);399400GLint maxCombinedClipAndCullDistances = 0;401glGetIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT, &maxCombinedClipAndCullDistances);402403EXPECT_GL_NO_ERROR();404EXPECT_GE(maxCombinedClipAndCullDistances, 8);405406GLboolean enabled = glIsEnabled(GL_CLIP_DISTANCE1_EXT);407EXPECT_GL_NO_ERROR();408EXPECT_EQ(enabled, GL_FALSE);409410glEnable(GL_CLIP_DISTANCE1_EXT);411EXPECT_GL_NO_ERROR();412glEnable(GL_CLIP_DISTANCE7_EXT);413EXPECT_GL_NO_ERROR();414enabled = glIsEnabled(GL_CLIP_DISTANCE1_EXT);415EXPECT_EQ(enabled, GL_TRUE);416417glDisable(GL_CLIP_DISTANCE1_EXT);418EXPECT_GL_NO_ERROR();419enabled = glIsEnabled(GL_CLIP_DISTANCE1_EXT);420EXPECT_EQ(enabled, GL_FALSE);421422EXPECT_EQ(glIsEnabled(GL_CLIP_DISTANCE7_EXT), GL_TRUE);423}424425// Check that the validation for EXT_clip_cull_distance extension is correct426// If gl_ClipDistance or gl_CullDistance is redeclared in some shader stages, the array size of the427// redeclared variables should match428TEST_P(ClipCullDistanceTest, SizeCheck)429{430ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));431432// Validate array size match of redeclared ClipDistance built-in433constexpr char kVSErrorClipDistance[] = R"(#version 300 es434#extension GL_EXT_clip_cull_distance : require435436out highp float gl_ClipDistance[1];437438uniform vec4 u_plane;439440in vec2 a_position;441442void main()443{444gl_Position = vec4(a_position, 0.0, 1.0);445446gl_ClipDistance[0] = dot(gl_Position, u_plane);447448gl_CullDistance[0] = dot(gl_Position, u_plane);449gl_CullDistance[1] = dot(gl_Position, u_plane);450})";451452constexpr char kFSErrorClipDistance[] = R"(#version 300 es453#extension GL_EXT_clip_cull_distance : require454in highp float gl_ClipDistance[2];455precision highp float;456out vec4 my_FragColor;457void main()458{459my_FragColor = vec4(gl_ClipDistance[0], gl_ClipDistance[1], gl_CullDistance[0], 1.0f);460})";461462GLProgram programClipDistance;463programClipDistance.makeRaster(kVSErrorClipDistance, kFSErrorClipDistance);464EXPECT_GL_FALSE(programClipDistance.valid());465466// Validate array size match of redeclared CullDistance built-in467constexpr char kVSErrorCullDistance[] = R"(#version 300 es468#extension GL_EXT_clip_cull_distance : require469470out highp float gl_CullDistance[1];471472uniform vec4 u_plane;473474in vec2 a_position;475476void main()477{478gl_Position = vec4(a_position, 0.0, 1.0);479480gl_CullDistance[0] = dot(gl_Position, u_plane);481482gl_ClipDistance[0] = dot(gl_Position, u_plane);483gl_ClipDistance[1] = dot(gl_Position, u_plane);484})";485486constexpr char kFSErrorCullDistance[] = R"(#version 300 es487#extension GL_EXT_clip_cull_distance : require488in highp float gl_CullDistance[2];489precision highp float;490out vec4 my_FragColor;491void main()492{493my_FragColor = vec4(gl_CullDistance[0], gl_CullDistance[1], gl_ClipDistance[0], 1.0f);494})";495496GLProgram programCullDistance;497programCullDistance.makeRaster(kVSErrorCullDistance, kFSErrorCullDistance);498EXPECT_GL_FALSE(programCullDistance.valid());499}500501// Write to one gl_ClipDistance element502TEST_P(ClipCullDistanceTest, OneClipDistance)503{504ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));505506constexpr char kVS[] = R"(#version 300 es507#extension GL_EXT_clip_cull_distance : require508509uniform vec4 u_plane;510511in vec2 a_position;512513void main()514{515gl_Position = vec4(a_position, 0.0, 1.0);516517gl_ClipDistance[0] = dot(gl_Position, u_plane);518})";519520ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());521glLinkProgram(programRed);522glUseProgram(programRed);523ASSERT_GL_NO_ERROR();524525glEnable(GL_CLIP_DISTANCE0_EXT);526527// Clear to blue528glClearColor(0, 0, 1, 1);529glClear(GL_COLOR_BUFFER_BIT);530531// Draw full screen quad with color red532glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);533EXPECT_GL_NO_ERROR();534drawQuad(programRed, "a_position", 0);535EXPECT_GL_NO_ERROR();536537// All pixels on the left of the plane x = -0.5 must be blue538GLuint x = 0;539GLuint y = 0;540GLuint width = getWindowWidth() / 4 - 1;541GLuint height = getWindowHeight();542EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::blue);543544// All pixels on the right of the plane x = -0.5 must be red545x = getWindowWidth() / 4 + 2;546y = 0;547width = getWindowWidth() - x;548height = getWindowHeight();549EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);550551// Clear to green552glClearColor(0, 1, 0, 1);553glClear(GL_COLOR_BUFFER_BIT);554555// Draw full screen quad with color red556glUniform4f(glGetUniformLocation(programRed, "u_plane"), -1, 0, 0, -0.5);557EXPECT_GL_NO_ERROR();558drawQuad(programRed, "a_position", 0);559EXPECT_GL_NO_ERROR();560561// All pixels on the left of the plane x = -0.5 must be red562x = 0;563y = 0;564width = getWindowWidth() / 4 - 1;565height = getWindowHeight();566EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);567568// All pixels on the right of the plane x = -0.5 must be green569x = getWindowWidth() / 4 + 2;570y = 0;571width = getWindowWidth() - x;572height = getWindowHeight();573EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::green);574575// Disable GL_CLIP_DISTANCE576glDisable(GL_CLIP_DISTANCE0_EXT);577drawQuad(programRed, "a_position", 0);578579// All pixels must be red580x = 0;581y = 0;582width = getWindowWidth();583height = getWindowHeight();584EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);585}586587// Write to 3 clip distances588TEST_P(ClipCullDistanceTest, ThreeClipDistances)589{590ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));591592constexpr char kVS[] = R"(#version 300 es593#extension GL_EXT_clip_cull_distance : require594595uniform vec4 u_plane[3];596597in vec2 a_position;598599void main()600{601gl_Position = vec4(a_position, 0.0, 1.0);602603gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);604gl_ClipDistance[3] = dot(gl_Position, u_plane[1]);605gl_ClipDistance[7] = dot(gl_Position, u_plane[2]);606})";607608ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());609glLinkProgram(programRed);610glUseProgram(programRed);611ASSERT_GL_NO_ERROR();612613// Enable 3 clip distances614glEnable(GL_CLIP_DISTANCE0_EXT);615glEnable(GL_CLIP_DISTANCE3_EXT);616glEnable(GL_CLIP_DISTANCE7_EXT);617ASSERT_GL_NO_ERROR();618619// Clear to blue620glClearColor(0, 0, 1, 1);621glClear(GL_COLOR_BUFFER_BIT);622623// Draw full screen quad with color red624// x = -0.5625glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);626// x = 0.5627glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);628// x + y = 1629glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);630EXPECT_GL_NO_ERROR();631drawQuad(programRed, "a_position", 0);632EXPECT_GL_NO_ERROR();633634// All pixels on the left of the plane x = -0.5 must be blue635GLuint x = 0;636GLuint y = 0;637GLuint width = getWindowWidth() / 4 - 1;638GLuint height = getWindowHeight();639EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::blue);640641// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right642// triangle643x = getWindowWidth() / 4 + 2;644y = 0;645width = getWindowWidth() / 2 - x;646height = getWindowHeight();647EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);648649std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());650glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,651actualColors.data());652for (int y = 0; y < getWindowHeight(); ++y)653{654for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)655{656const int currentPosition = y * getWindowHeight() + x;657658if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)659{660// bottom left triangle clipped by x=0.5 plane661EXPECT_EQ(GLColor::red, actualColors[currentPosition]);662}663else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)664{665// upper right triangle plus right of x=0.5 plane666EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);667}668}669}670671// Clear to green672glClearColor(0, 1, 0, 1);673glClear(GL_COLOR_BUFFER_BIT);674675// Disable gl_ClipDistance[3]676glDisable(GL_CLIP_DISTANCE3_EXT);677678// Draw full screen quad with color red679EXPECT_GL_NO_ERROR();680drawQuad(programRed, "a_position", 0);681EXPECT_GL_NO_ERROR();682683// All pixels on the left of the plane x = -0.5 must be green684for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)685{686for (int y = 0; y < getWindowHeight(); ++y)687{688EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);689}690}691692// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right693// triangle694x = getWindowWidth() / 4 + 2;695y = 0;696width = getWindowWidth() / 2 - x;697height = getWindowHeight();698EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);699700glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,701actualColors.data());702for (int y = 0; y < getWindowHeight(); ++y)703{704for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)705{706const int currentPosition = y * getWindowHeight() + x;707708if (x < getWindowWidth() * 3 / 2 - y - 1)709{710// bottom left triangle711EXPECT_EQ(GLColor::red, actualColors[currentPosition]);712}713else if (x > getWindowWidth() * 3 / 2 - y + 1)714{715// upper right triangle716EXPECT_EQ(GLColor::green, actualColors[currentPosition]);717}718}719}720}721722// Redeclare gl_ClipDistance in shader with explicit size, also use it in a global function723// outside main()724TEST_P(ClipCullDistanceTest, ThreeClipDistancesRedeclared)725{726ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));727728constexpr char kVS[] = R"(#version 300 es729#extension GL_EXT_clip_cull_distance : require730731out highp float gl_ClipDistance[3];732733void computeClipDistances(in vec4 position, in vec4 plane[3])734{735gl_ClipDistance[0] = dot(position, plane[0]);736gl_ClipDistance[1] = dot(position, plane[1]);737gl_ClipDistance[2] = dot(position, plane[2]);738}739740uniform vec4 u_plane[3];741742in vec2 a_position;743744void main()745{746gl_Position = vec4(a_position, 0.0, 1.0);747748computeClipDistances(gl_Position, u_plane);749})";750751ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());752glLinkProgram(programRed);753glUseProgram(programRed);754ASSERT_GL_NO_ERROR();755756// Enable 3 clip distances757glEnable(GL_CLIP_DISTANCE0_EXT);758glEnable(GL_CLIP_DISTANCE1_EXT);759glEnable(GL_CLIP_DISTANCE2_EXT);760ASSERT_GL_NO_ERROR();761762// Clear to blue763glClearColor(0, 0, 1, 1);764glClear(GL_COLOR_BUFFER_BIT);765766// Draw full screen quad with color red767// x = -0.5768glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);769// x = 0.5770glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);771// x + y = 1772glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);773EXPECT_GL_NO_ERROR();774drawQuad(programRed, "a_position", 0);775EXPECT_GL_NO_ERROR();776777// All pixels on the left of the plane x = -0.5 must be blue778GLuint x = 0;779GLuint y = 0;780GLuint width = getWindowWidth() / 4 - 1;781GLuint height = getWindowHeight();782EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::blue);783784// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right785// triangle786x = getWindowWidth() / 4 + 2;787y = 0;788width = getWindowWidth() / 2 - x;789height = getWindowHeight();790EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);791792std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());793glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,794actualColors.data());795for (int y = 0; y < getWindowHeight(); ++y)796{797for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)798{799const int currentPosition = y * getWindowHeight() + x;800801if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)802{803// bottom left triangle clipped by x=0.5 plane804EXPECT_EQ(GLColor::red, actualColors[currentPosition]);805}806else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)807{808// upper right triangle plus right of x=0.5 plane809EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);810}811}812}813}814815// Write to one gl_CullDistance element816TEST_P(ClipCullDistanceTest, OneCullDistance)817{818ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));819820constexpr char kVS[] = R"(#version 300 es821#extension GL_EXT_clip_cull_distance : require822823uniform vec4 u_plane;824825in vec2 a_position;826827void main()828{829gl_Position = vec4(a_position, 0.0, 1.0);830831gl_CullDistance[0] = dot(gl_Position, u_plane);832})";833834ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());835glLinkProgram(programRed);836glUseProgram(programRed);837ASSERT_GL_NO_ERROR();838839// Clear to blue840glClearColor(0, 0, 1, 1);841glClear(GL_COLOR_BUFFER_BIT);842843// Draw full screen quad with color red844glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);845EXPECT_GL_NO_ERROR();846drawQuad(programRed, "a_position", 0);847EXPECT_GL_NO_ERROR();848849// All pixels must be red850GLuint x = 0;851GLuint y = 0;852GLuint width = getWindowWidth();853GLuint height = getWindowHeight();854EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);855856// Clear to green857glClearColor(0, 1, 0, 1);858glClear(GL_COLOR_BUFFER_BIT);859860// Draw full screen quad with color red861glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 1, 0, 0);862EXPECT_GL_NO_ERROR();863drawQuad(programRed, "a_position", 0);864EXPECT_GL_NO_ERROR();865866// All pixels on the plane y >= -x must be red867std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());868glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,869actualColors.data());870for (int x = 0; x < getWindowWidth(); ++x)871{872for (int y = 0; y < getWindowHeight(); ++y)873{874const int currentPosition = y * getWindowHeight() + x;875876if ((x + y) >= 0)877{878EXPECT_EQ(GLColor::red, actualColors[currentPosition]);879}880else881{882EXPECT_EQ(GLColor::green, actualColors[currentPosition]);883}884}885}886}887888// Write to 4 clip distances889TEST_P(ClipCullDistanceTest, FourClipDistances)890{891ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));892893constexpr char kVS[] = R"(#version 300 es894#extension GL_EXT_clip_cull_distance : require895896in vec2 a_position;897uniform vec4 u_plane[4];898899void main()900{901gl_Position = vec4(a_position, 0.0, 1.0);902903gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);904gl_ClipDistance[1] = dot(gl_Position, u_plane[1]);905gl_ClipDistance[2] = dot(gl_Position, u_plane[2]);906gl_ClipDistance[3] = dot(gl_Position, u_plane[3]);907})";908909ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());910glUseProgram(programRed);911ASSERT_GL_NO_ERROR();912913// Enable 3 clip distances914glEnable(GL_CLIP_DISTANCE0_EXT);915glEnable(GL_CLIP_DISTANCE2_EXT);916glEnable(GL_CLIP_DISTANCE3_EXT);917ASSERT_GL_NO_ERROR();918919// Disable 1 clip distances920glDisable(GL_CLIP_DISTANCE1_EXT);921ASSERT_GL_NO_ERROR();922923// Clear to blue924glClearColor(0, 0, 1, 1);925glClear(GL_COLOR_BUFFER_BIT);926927constexpr unsigned int kNumVertices = 12;928const std::array<Vector3, kNumVertices> quadVertices = {929{Vector3(-1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f),930Vector3(1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, -1.0f, 0.0f),931Vector3(1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, -1.0f, 0.0f),932Vector3(-1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, 1.0f, 0.0f)}};933934GLBuffer vertexBuffer;935glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);936glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),937GL_STATIC_DRAW);938ASSERT_GL_NO_ERROR();939940GLint positionLocation = glGetAttribLocation(programRed, "a_position");941glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);942ASSERT_GL_NO_ERROR();943944glEnableVertexAttribArray(positionLocation);945ASSERT_GL_NO_ERROR();946947// Draw full screen quad and small size triangle with color red948// y <= 1.0f949glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);950// y >= 0.5f951glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);952// y >= 3x-0.5f953glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);954// y >= -3x-0.5f955glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);956EXPECT_GL_NO_ERROR();957958glDrawArrays(GL_TRIANGLES, 0, kNumVertices);959EXPECT_GL_NO_ERROR();960961const int windowWidth = getWindowWidth();962const int windowHeight = getWindowHeight();963auto checkLeftPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {964return (3 * (x - (windowWidth / 2 - 1)) - (windowHeight / 4 + 1) + y);965};966auto checkRightPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {967return (-3 * (x - (windowWidth / 2)) - (windowHeight / 4 + 1) + y);968};969970// Only pixels in the triangle must be red971std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());972glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,973actualColors.data());974for (int x = 0; x < getWindowWidth(); ++x)975{976for (int y = 0; y < getWindowHeight(); ++y)977{978// The drawing method of Swiftshader and Native graphic card is different. So the979// compare function doesn't check the value on the line.980const int currentPosition = y * getWindowHeight() + x;981982if (checkLeftPlaneFunc(x, y) > 0 && checkRightPlaneFunc(x, y) > 0)983{984EXPECT_EQ(GLColor::red, actualColors[currentPosition]);985}986else if (checkLeftPlaneFunc(x, y) < 0 || checkRightPlaneFunc(x, y) < 0)987{988EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);989}990}991}992}993994// Write to 4 cull distances995TEST_P(ClipCullDistanceTest, FourCullDistances)996{997ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));998999// SwiftShader bug: http://anglebug.com/54511000ANGLE_SKIP_TEST_IF(isSwiftshader());10011002constexpr char kVS[] = R"(#version 300 es1003#extension GL_EXT_clip_cull_distance : require10041005uniform vec4 u_plane[4];10061007in vec2 a_position;10081009void main()1010{1011gl_Position = vec4(a_position, 0.0, 1.0);10121013gl_CullDistance[0] = dot(gl_Position, u_plane[0]);1014gl_CullDistance[1] = dot(gl_Position, u_plane[1]);1015gl_CullDistance[2] = dot(gl_Position, u_plane[2]);1016gl_CullDistance[3] = dot(gl_Position, u_plane[3]);1017})";10181019ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());1020glLinkProgram(programRed);1021glUseProgram(programRed);1022ASSERT_GL_NO_ERROR();10231024// Clear to blue1025glClearColor(0, 0, 1, 1);1026glClear(GL_COLOR_BUFFER_BIT);10271028constexpr unsigned int kNumVertices = 12;1029const std::array<Vector3, kNumVertices> quadVertices = {1030{Vector3(-1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f),1031Vector3(1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, -1.0f, 0.0f),1032Vector3(1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, -1.0f, 0.0f),1033Vector3(-1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, 1.0f, 0.0f)}};10341035GLBuffer vertexBuffer;1036glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);1037glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),1038GL_STATIC_DRAW);1039ASSERT_GL_NO_ERROR();10401041GLint positionLocation = glGetAttribLocation(programRed, "a_position");1042glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);1043ASSERT_GL_NO_ERROR();10441045glEnableVertexAttribArray(positionLocation);1046ASSERT_GL_NO_ERROR();10471048// Draw full screen quad and small size triangle with color red1049// y <= 1.0f1050glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);1051// y >= 0.5f1052glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);1053// y >= 3x-0.5f1054glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);1055// y >= -3x-0.5f1056glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);1057EXPECT_GL_NO_ERROR();10581059glDrawArrays(GL_TRIANGLES, 0, kNumVertices);1060EXPECT_GL_NO_ERROR();10611062// Only pixels in the triangle must be red1063std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());1064glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,1065actualColors.data());1066for (int x = 0; x < getWindowWidth(); ++x)1067{1068for (int y = 0; y < getWindowHeight(); ++y)1069{1070const int currentPosition = y * getWindowHeight() + x;10711072if (y > x || y >= -x + getWindowHeight() - 1)1073{1074EXPECT_EQ(GLColor::red, actualColors[currentPosition]);1075}1076else1077{1078EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);1079}1080}1081}1082}10831084// Verify that EXT_clip_cull_distance works with EXT_geometry_shader1085TEST_P(ClipCullDistanceTest, ClipDistanceInteractWithGeometryShader)1086{1087// TODO: http://anglebug.com/54661088// After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally1089// implemented to support the geometry shader. And then, this skip can be removed.1090ANGLE_SKIP_TEST_IF(IsVulkan());10911092ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance") ||1093!IsGLExtensionEnabled("GL_EXT_geometry_shader"));10941095constexpr char kVS[] = R"(#version 310 es1096#extension GL_EXT_clip_cull_distance : require1097#extension GL_EXT_geometry_shader : require10981099in vec2 a_position;1100uniform vec4 u_plane[4];11011102void main()1103{1104gl_Position = vec4(a_position, 0.0, 1.0);11051106gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);1107gl_ClipDistance[1] = dot(gl_Position, u_plane[1]);1108gl_ClipDistance[2] = dot(gl_Position, u_plane[2]);1109gl_ClipDistance[3] = dot(gl_Position, u_plane[3]);1110})";11111112constexpr char kGS[] = R"(#version 310 es1113#extension GL_EXT_clip_cull_distance : require1114#extension GL_EXT_geometry_shader : require11151116layout (triangles) in;1117layout (triangle_strip, max_vertices = 3) out;11181119in gl_PerVertex {1120highp vec4 gl_Position;1121highp float gl_ClipDistance[];1122} gl_in[];11231124out gl_PerVertex {1125highp vec4 gl_Position;1126highp float gl_ClipDistance[];1127};11281129uniform vec4 u_plane[4];11301131void GetNewPosition(int i)1132{1133gl_Position = 2.0f * gl_in[i].gl_Position;11341135for (int index = 0 ; index < 4 ; index++)1136{1137if (gl_in[i].gl_ClipDistance[index] < 0.0f)1138{1139gl_ClipDistance[index] = dot(gl_Position, u_plane[index]);1140}1141}1142EmitVertex();1143}11441145void main()1146{1147for (int i = 0 ; i < 3 ; i++)1148{1149GetNewPosition(i);1150}1151EndPrimitive();1152})";11531154ANGLE_GL_PROGRAM_WITH_GS(programRed, kVS, kGS, essl31_shaders::fs::Red());1155glUseProgram(programRed);1156ASSERT_GL_NO_ERROR();11571158// Enable 3 clip distances1159glEnable(GL_CLIP_DISTANCE0_EXT);1160glEnable(GL_CLIP_DISTANCE2_EXT);1161glEnable(GL_CLIP_DISTANCE3_EXT);1162ASSERT_GL_NO_ERROR();11631164// Disable 1 clip distances1165glDisable(GL_CLIP_DISTANCE1_EXT);1166ASSERT_GL_NO_ERROR();11671168// Clear to blue1169glClearColor(0, 0, 1, 1);1170glClear(GL_COLOR_BUFFER_BIT);11711172constexpr unsigned int kNumVertices = 12;1173const std::array<Vector3, kNumVertices> quadVertices = {1174{Vector3(-0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, 0.5f, 0.0f),1175Vector3(0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, -0.5f, 0.0f),1176Vector3(0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, -0.5f, 0.0f),1177Vector3(-0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, 0.5f, 0.0f)}};11781179GLBuffer vertexBuffer;1180glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);1181glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),1182GL_STATIC_DRAW);1183ASSERT_GL_NO_ERROR();11841185GLint positionLocation = glGetAttribLocation(programRed, "a_position");1186glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);1187ASSERT_GL_NO_ERROR();11881189glEnableVertexAttribArray(positionLocation);1190ASSERT_GL_NO_ERROR();11911192// Draw full screen quad and small size triangle with color red1193// y <= 1.0f1194glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);1195// y >= 0.5f1196glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);1197// y >= 3x-0.5f1198glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);1199// y >= -3x-0.5f1200glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);1201EXPECT_GL_NO_ERROR();12021203glDrawArrays(GL_TRIANGLES, 0, kNumVertices);1204EXPECT_GL_NO_ERROR();12051206const int windowWidth = getWindowWidth();1207const int windowHeight = getWindowHeight();1208auto checkLeftPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {1209return (3 * (x - (windowWidth / 2 - 1)) - (windowHeight / 4 + 1) + y);1210};1211auto checkRightPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {1212return (-3 * (x - (windowWidth / 2)) - (windowHeight / 4 + 1) + y);1213};12141215// Only pixels in the triangle must be red1216std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());1217glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,1218actualColors.data());1219for (int x = 0; x < getWindowWidth(); ++x)1220{1221for (int y = 0; y < getWindowHeight(); ++y)1222{1223// The drawing method of Swiftshader and Native graphic card is different. So the1224// compare function doesn't check the value on the line.1225const int currentPosition = y * getWindowHeight() + x;12261227if (checkLeftPlaneFunc(x, y) > 0 && checkRightPlaneFunc(x, y) > 0)1228{1229EXPECT_EQ(GLColor::red, actualColors[currentPosition]);1230}1231else if (checkLeftPlaneFunc(x, y) < 0 || checkRightPlaneFunc(x, y) < 0)1232{1233EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);1234}1235}1236}1237}12381239// Verify that EXT_clip_cull_distance works with EXT_geometry_shader1240TEST_P(ClipCullDistanceTest, CullDistanceInteractWithGeometryShader)1241{1242// TODO: http://anglebug.com/54661243// After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally1244// implemented to support the geometry shader. And then, this skip can be removed.1245ANGLE_SKIP_TEST_IF(IsVulkan());12461247ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance") ||1248!IsGLExtensionEnabled("GL_EXT_geometry_shader"));12491250constexpr char kVS[] = R"(#version 310 es1251#extension GL_EXT_clip_cull_distance : require1252#extension GL_EXT_geometry_shader : require12531254in vec2 a_position;1255uniform vec4 u_plane[4];12561257void main()1258{1259gl_Position = vec4(a_position, 0.0, 1.0);12601261gl_CullDistance[0] = dot(gl_Position, u_plane[0]);1262gl_CullDistance[1] = dot(gl_Position, u_plane[1]);1263gl_CullDistance[2] = dot(gl_Position, u_plane[2]);1264gl_CullDistance[3] = dot(gl_Position, u_plane[3]);1265})";12661267constexpr char kGS[] = R"(#version 310 es1268#extension GL_EXT_clip_cull_distance : require1269#extension GL_EXT_geometry_shader : require12701271layout (triangles) in;1272layout (triangle_strip, max_vertices = 3) out;12731274in gl_PerVertex {1275highp vec4 gl_Position;1276highp float gl_CullDistance[];1277} gl_in[];12781279out gl_PerVertex {1280highp vec4 gl_Position;1281highp float gl_CullDistance[];1282};12831284uniform vec4 u_plane[4];12851286void GetNewPosition(int i)1287{1288gl_Position = 2.0f * gl_in[i].gl_Position;12891290for (int index = 0 ; index < 4 ; index++)1291{1292if (gl_in[i].gl_CullDistance[index] < 0.0f)1293{1294gl_CullDistance[index] = dot(gl_Position, u_plane[index]);1295}1296}1297EmitVertex();1298}12991300void main()1301{1302for (int i = 0 ; i < 3 ; i++)1303{1304GetNewPosition(i);1305}1306EndPrimitive();1307})";13081309ANGLE_GL_PROGRAM_WITH_GS(programRed, kVS, kGS, essl31_shaders::fs::Red());1310glUseProgram(programRed);1311ASSERT_GL_NO_ERROR();13121313// Clear to blue1314glClearColor(0, 0, 1, 1);1315glClear(GL_COLOR_BUFFER_BIT);13161317constexpr unsigned int kNumVertices = 12;1318const std::array<Vector3, kNumVertices> quadVertices = {1319{Vector3(-0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, 0.5f, 0.0f),1320Vector3(0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, -0.5f, 0.0f),1321Vector3(0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, -0.5f, 0.0f),1322Vector3(-0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, 0.5f, 0.0f)}};13231324GLBuffer vertexBuffer;1325glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);1326glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),1327GL_STATIC_DRAW);1328ASSERT_GL_NO_ERROR();13291330GLint positionLocation = glGetAttribLocation(programRed, "a_position");1331glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);1332ASSERT_GL_NO_ERROR();13331334glEnableVertexAttribArray(positionLocation);1335ASSERT_GL_NO_ERROR();13361337// Draw full screen quad and small size triangle with color red1338// y <= 1.0f1339glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);1340// y >= 0.5f1341glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);1342// y >= 3x-0.5f1343glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);1344// y >= -3x-0.5f1345glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);1346EXPECT_GL_NO_ERROR();13471348glDrawArrays(GL_TRIANGLES, 0, kNumVertices);1349EXPECT_GL_NO_ERROR();13501351// Only pixels in the triangle must be red1352std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());1353glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,1354actualColors.data());1355for (int x = 0; x < getWindowWidth(); ++x)1356{1357for (int y = 0; y < getWindowHeight(); ++y)1358{1359const int currentPosition = y * getWindowHeight() + x;13601361if (y > x || y >= -x + getWindowHeight() - 1)1362{1363EXPECT_EQ(GLColor::red, actualColors[currentPosition]);1364}1365else1366{1367EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);1368}1369}1370}1371}13721373ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(ClipDistanceTest, WithDirectSPIRVGeneration(ES3_VULKAN()));13741375GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClipCullDistanceTest);1376ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(ClipCullDistanceTest,1377WithDirectSPIRVGeneration(ES3_VULKAN()),1378WithDirectSPIRVGeneration(ES31_VULKAN()));137913801381