Path: blob/main_old/src/tests/gl_tests/CopyTexImageTest.cpp
1693 views
//1// Copyright 2015 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//56#include "test_utils/ANGLETest.h"7#include "test_utils/gl_raii.h"89namespace angle10{1112class CopyTexImageTest : public ANGLETest13{14protected:15CopyTexImageTest()16{17setWindowWidth(32);18setWindowHeight(32);19setConfigRedBits(8);20setConfigGreenBits(8);21setConfigBlueBits(8);22setConfigAlphaBits(8);23}2425void testSetUp() override26{27mTextureProgram =28CompileProgram(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());29if (mTextureProgram == 0)30{31FAIL() << "shader compilation failed.";32}3334mTextureUniformLocation =35glGetUniformLocation(mTextureProgram, essl1_shaders::Texture2DUniform());3637ASSERT_GL_NO_ERROR();38}3940void testTearDown() override { glDeleteProgram(mTextureProgram); }4142void initializeResources(GLenum format, GLenum type)43{44for (size_t i = 0; i < kFboCount; ++i)45{46glBindTexture(GL_TEXTURE_2D, mFboTextures[i]);47glTexImage2D(GL_TEXTURE_2D, 0, format, kFboSizes[i], kFboSizes[i], 0, format, type,48nullptr);4950// Disable mipmapping51glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);52glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);5354glBindFramebuffer(GL_FRAMEBUFFER, mFbos[i]);55glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,56mFboTextures[i], 0);5758glClearColor(kFboColors[i][0], kFboColors[i][1], kFboColors[i][2], kFboColors[i][3]);59glClear(GL_COLOR_BUFFER_BIT);60}6162ASSERT_GL_NO_ERROR();63}6465void verifyResults(GLuint texture,66const GLubyte data[4],67GLint fboSize,68GLint xs,69GLint ys,70GLint xe,71GLint ye)72{73glViewport(0, 0, fboSize, fboSize);7475glBindFramebuffer(GL_FRAMEBUFFER, 0);7677// Draw a quad with the target texture78glUseProgram(mTextureProgram);79glBindTexture(GL_TEXTURE_2D, texture);80glUniform1i(mTextureUniformLocation, 0);8182drawQuad(mTextureProgram, essl1_shaders::PositionAttrib(), 0.5f);8384// Expect that the rendered quad has the same color as the source texture85EXPECT_PIXEL_NEAR(xs, ys, data[0], data[1], data[2], data[3], 1.0);86EXPECT_PIXEL_NEAR(xs, ye - 1, data[0], data[1], data[2], data[3], 1.0);87EXPECT_PIXEL_NEAR(xe - 1, ys, data[0], data[1], data[2], data[3], 1.0);88EXPECT_PIXEL_NEAR(xe - 1, ye - 1, data[0], data[1], data[2], data[3], 1.0);89EXPECT_PIXEL_NEAR((xs + xe) / 2, (ys + ye) / 2, data[0], data[1], data[2], data[3], 1.0);90}9192void runCopyTexImageTest(GLenum format, GLubyte expected[3][4])93{94GLTexture tex;95glBindTexture(GL_TEXTURE_2D, tex);9697// Disable mipmapping98glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);99glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);100101// Perform the copy multiple times.102//103// - The first time, a new texture is created104// - The second time, as the fbo size is the same as previous, the texture storage is not105// recreated.106// - The third time, the fbo size is different, so a new texture is created.107for (size_t i = 0; i < kFboCount; ++i)108{109glBindFramebuffer(GL_FRAMEBUFFER, mFbos[i]);110111glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[i], kFboSizes[i], 0);112ASSERT_GL_NO_ERROR();113114verifyResults(tex, expected[i], kFboSizes[i], 0, 0, kFboSizes[i], kFboSizes[i]);115}116}117118void runCopyTexSubImageTest(GLenum format, GLubyte expected[3][4])119{120GLTexture tex;121glBindTexture(GL_TEXTURE_2D, tex);122123// Disable mipmapping124glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);125glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);126127// Create the texture with copy of the first fbo.128glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);129glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[0], kFboSizes[0], 0);130ASSERT_GL_NO_ERROR();131132verifyResults(tex, expected[0], kFboSizes[0], 0, 0, kFboSizes[0], kFboSizes[0]);133134// Make sure out-of-bound writes to the texture return invalid value.135glBindFramebuffer(GL_FRAMEBUFFER, mFbos[1]);136137// xoffset < 0 and yoffset < 0138glCopyTexSubImage2D(GL_TEXTURE_2D, 0, -1, -1, 0, 0, kFboSizes[0], kFboSizes[0]);139ASSERT_GL_ERROR(GL_INVALID_VALUE);140141// xoffset + width > w and yoffset + height > h142glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 0, 0, kFboSizes[0], kFboSizes[0]);143ASSERT_GL_ERROR(GL_INVALID_VALUE);144145// xoffset + width > w and yoffset + height > h, out of bounds146glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -1, -1, 1 + kFboSizes[0], 1 + kFboSizes[0]);147ASSERT_GL_ERROR(GL_INVALID_VALUE);148149// Copy the second fbo over a portion of the image.150GLint offset = kFboSizes[0] / 2;151GLint extent = kFboSizes[0] - offset;152153glCopyTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, kFboSizes[1] / 2, kFboSizes[1] / 2,154extent, extent);155ASSERT_GL_NO_ERROR();156157verifyResults(tex, expected[1], kFboSizes[0], offset, offset, kFboSizes[0], kFboSizes[0]);158159// The rest of the image should be untouched160verifyResults(tex, expected[0], kFboSizes[0], 0, 0, offset, offset);161verifyResults(tex, expected[0], kFboSizes[0], offset, 0, kFboSizes[0], offset);162verifyResults(tex, expected[0], kFboSizes[0], 0, offset, offset, kFboSizes[0]);163164// Copy the third fbo over another portion of the image.165glBindFramebuffer(GL_FRAMEBUFFER, mFbos[2]);166167offset = kFboSizes[0] / 4;168extent = kFboSizes[0] - offset;169170// While width and height are set as 3/4 of the size, the fbo offset is given such that171// after clipping, width and height are effectively 1/2 of the size.172GLint srcOffset = kFboSizes[2] - kFboSizes[0] / 2;173GLint effectiveExtent = kFboSizes[0] / 2;174175glCopyTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, srcOffset, srcOffset, extent, extent);176ASSERT_GL_NO_ERROR();177178verifyResults(tex, expected[2], kFboSizes[0], offset, offset, effectiveExtent,179effectiveExtent);180181// The rest of the image should be untouched182verifyResults(tex, expected[1], kFboSizes[0], offset + effectiveExtent, kFboSizes[0] / 2,183kFboSizes[0], kFboSizes[0]);184verifyResults(tex, expected[1], kFboSizes[0], kFboSizes[0] / 2, offset + effectiveExtent,185kFboSizes[0], kFboSizes[0]);186187verifyResults(tex, expected[0], kFboSizes[0], 0, 0, kFboSizes[0], offset);188verifyResults(tex, expected[0], kFboSizes[0], 0, 0, offset, kFboSizes[0]);189verifyResults(tex, expected[0], kFboSizes[0], offset + effectiveExtent, 0, kFboSizes[0],190kFboSizes[0] / 2);191verifyResults(tex, expected[0], kFboSizes[0], 0, offset + effectiveExtent, kFboSizes[0] / 2,192kFboSizes[0]);193}194195GLuint mTextureProgram;196GLint mTextureUniformLocation;197198static constexpr uint32_t kFboCount = 3;199GLFramebuffer mFbos[kFboCount];200GLTexture mFboTextures[kFboCount];201202static constexpr uint32_t kFboSizes[kFboCount] = {16, 16, 32};203static constexpr GLfloat kFboColors[kFboCount][4] = {{0.25f, 1.0f, 0.75f, 0.5f},204{1.0f, 0.75f, 0.5f, 0.25f},205{0.5f, 0.25f, 1.0f, 0.75f}};206};207208// Until C++17, need to redundantly declare the constexpr members outside the class (only the209// arrays, because the others are already const-propagated and not needed by the linker).210constexpr uint32_t CopyTexImageTest::kFboSizes[];211constexpr GLfloat CopyTexImageTest::kFboColors[][4];212213TEST_P(CopyTexImageTest, RGBAToRGB)214{215GLubyte expected[3][4] = {216{64, 255, 191, 255},217{255, 191, 127, 255},218{127, 64, 255, 255},219};220221initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);222runCopyTexImageTest(GL_RGB, expected);223}224225TEST_P(CopyTexImageTest, RGBAToL)226{227GLubyte expected[3][4] = {228{64, 64, 64, 255},229{255, 255, 255, 255},230{127, 127, 127, 255},231};232233initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);234runCopyTexImageTest(GL_LUMINANCE, expected);235}236237TEST_P(CopyTexImageTest, RGBToL)238{239GLubyte expected[3][4] = {240{64, 64, 64, 255},241{255, 255, 255, 255},242{127, 127, 127, 255},243};244245initializeResources(GL_RGB, GL_UNSIGNED_BYTE);246runCopyTexImageTest(GL_LUMINANCE, expected);247}248249TEST_P(CopyTexImageTest, RGBAToLA)250{251GLubyte expected[3][4] = {252{64, 64, 64, 127},253{255, 255, 255, 64},254{127, 127, 127, 191},255};256257initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);258runCopyTexImageTest(GL_LUMINANCE_ALPHA, expected);259}260261TEST_P(CopyTexImageTest, RGBAToA)262{263GLubyte expected[3][4] = {264{0, 0, 0, 127},265{0, 0, 0, 64},266{0, 0, 0, 191},267};268269initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);270runCopyTexImageTest(GL_ALPHA, expected);271}272273TEST_P(CopyTexImageTest, SubImageRGBAToRGB)274{275GLubyte expected[3][4] = {276{64, 255, 191, 255},277{255, 191, 127, 255},278{127, 64, 255, 255},279};280281initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);282runCopyTexSubImageTest(GL_RGB, expected);283}284285TEST_P(CopyTexImageTest, SubImageRGBAToL)286{287GLubyte expected[3][4] = {288{64, 64, 64, 255},289{255, 255, 255, 255},290{127, 127, 127, 255},291};292293initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);294runCopyTexSubImageTest(GL_LUMINANCE, expected);295}296297TEST_P(CopyTexImageTest, SubImageRGBAToLA)298{299GLubyte expected[3][4] = {300{64, 64, 64, 127},301{255, 255, 255, 64},302{127, 127, 127, 191},303};304305initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);306runCopyTexSubImageTest(GL_LUMINANCE_ALPHA, expected);307}308309TEST_P(CopyTexImageTest, SubImageRGBToL)310{311GLubyte expected[3][4] = {312{64, 64, 64, 255},313{255, 255, 255, 255},314{127, 127, 127, 255},315};316317initializeResources(GL_RGB, GL_UNSIGNED_BYTE);318runCopyTexSubImageTest(GL_LUMINANCE, expected);319}320321// Read default framebuffer with glCopyTexImage2D().322TEST_P(CopyTexImageTest, DefaultFramebuffer)323{324// Seems to be a bug in Mesa with the GLX back end: cannot read framebuffer until we draw to it.325// glCopyTexImage2D() below will fail without this clear.326glClear(GL_COLOR_BUFFER_BIT);327328const GLint w = getWindowWidth(), h = getWindowHeight();329GLTexture tex;330glBindTexture(GL_TEXTURE_2D, tex);331glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);332glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, w, h, 0);333EXPECT_GL_NO_ERROR();334}335336// Read default framebuffer with glCopyTexSubImage2D().337TEST_P(CopyTexImageTest, SubDefaultFramebuffer)338{339// Seems to be a bug in Mesa with the GLX back end: cannot read framebuffer until we draw to it.340// glCopyTexSubImage2D() below will fail without this clear.341glClear(GL_COLOR_BUFFER_BIT);342343const GLint w = getWindowWidth(), h = getWindowHeight();344GLTexture tex;345glBindTexture(GL_TEXTURE_2D, tex);346glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);347glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w, h);348EXPECT_GL_NO_ERROR();349}350351// Calling CopyTexSubImage from cubeMap texture.352TEST_P(CopyTexImageTest, CopyTexSubImageFromCubeMap)353{354constexpr GLsizei kCubeMapFaceCount = 6;355356// The framebuffer will be a face of a cube map with a different colors for each face. Each357// glCopyTexSubImage2D will take one face of this image to copy over a pixel in a 1x6358// framebuffer.359GLColor fboPixels[kCubeMapFaceCount] = {GLColor::red, GLColor::yellow, GLColor::green,360GLColor::cyan, GLColor::blue, GLColor::magenta};361GLColor whitePixels[kCubeMapFaceCount] = {GLColor::white, GLColor::white, GLColor::white,362GLColor::white, GLColor::white, GLColor::white};363364GLTexture fboTex;365glBindTexture(GL_TEXTURE_CUBE_MAP, fboTex);366for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;367face++)368{369GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;370371glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &fboPixels[faceIndex]);372}373374GLTexture dstTex;375glBindTexture(GL_TEXTURE_2D, dstTex);376glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kCubeMapFaceCount, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,377whitePixels);378379GLFramebuffer fbo;380glBindFramebuffer(GL_FRAMEBUFFER, fbo);381382for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;383face++)384{385GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;386387glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face, fboTex, 0);388389ASSERT_GL_NO_ERROR();390ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));391392// Copy the fbo (a cube map face) into a pixel of the destination texture.393glCopyTexSubImage2D(GL_TEXTURE_2D, 0, faceIndex, 0, 0, 0, 1, 1);394}395396// Make sure all the copies are done correctly.397glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTex, 0);398399ASSERT_GL_NO_ERROR();400ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));401402for (GLsizei faceIndex = 0; faceIndex < kCubeMapFaceCount; ++faceIndex)403{404EXPECT_PIXEL_COLOR_EQ(faceIndex, 0, fboPixels[faceIndex]);405}406}407408// Calling CopyTexSubImage to a non-cube-complete texture.409TEST_P(CopyTexImageTest, CopyTexSubImageToNonCubeCompleteDestination)410{411// TODO(hqle): Find what wrong with NVIDIA GPU. http://anglebug.com/4137412ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsMetal());413414constexpr GLsizei kCubeMapFaceCount = 6;415416// The framebuffer will be a 1x6 image with 6 different colors. Each glCopyTexSubImage2D will417// take one pixel of this image to copy over each face of a cube map.418GLColor fboPixels[kCubeMapFaceCount] = {GLColor::red, GLColor::yellow, GLColor::green,419GLColor::cyan, GLColor::blue, GLColor::magenta};420GLColor whitePixel = GLColor::white;421422GLTexture fboTex;423glBindTexture(GL_TEXTURE_2D, fboTex);424glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kCubeMapFaceCount, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,425fboPixels);426427GLFramebuffer fbo;428glBindFramebuffer(GL_FRAMEBUFFER, fbo);429glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);430431ASSERT_GL_NO_ERROR();432ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));433434GLTexture cubeMap;435glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMap);436437for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;438face++)439{440GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;441442// Initialize the face with a color not found in the fbo.443glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitePixel);444445// Copy one pixel from the fbo into this face. The first 5 copies are done on a446// non-cube-complete texture.447glCopyTexSubImage2D(face, 0, 0, 0, faceIndex, 0, 1, 1);448}449450// Make sure all the copies are done correctly.451for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;452face++)453{454GLsizei faceIndex = face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;455456glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face, cubeMap, 0);457458ASSERT_GL_NO_ERROR();459ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));460461EXPECT_PIXEL_COLOR_EQ(0, 0, fboPixels[faceIndex]);462}463}464465// Deleting textures after copying to them. http://anglebug.com/4267466TEST_P(CopyTexImageTest, DeleteAfterCopyingToTextures)467{468// TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.469ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());470471GLTexture texture;472glBindTexture(GL_TEXTURE_2D, texture);473glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);474glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);475glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);476glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);477glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);478479GLTexture texture2;480glBindTexture(GL_TEXTURE_2D, texture2);481glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);482glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);483glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);484glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);485glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);486487GLFramebuffer framebuffer;488glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);489glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);490ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);491492// Perform CopyTexImage2D493glBindTexture(GL_TEXTURE_2D, texture);494glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 0, 0, 2, 2, 0);495ASSERT_GL_NO_ERROR();496// Not necessary to do any CopyTexImage2D operations to texture2.497498// Perform CopyTexSubImage2D499glBindTexture(GL_TEXTURE_2D, texture);500glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);501ASSERT_GL_NO_ERROR();502glBindTexture(GL_TEXTURE_2D, texture2);503glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);504ASSERT_GL_NO_ERROR();505506// Clean up - provokes crash on buggy drivers.507texture.reset();508// Crashes on Intel GPUs on macOS.509texture2.reset();510}511// Test if glCopyTexImage2D() implementation performs conversions well from GL_TEXTURE_3D to512// GL_TEXTURE_2D.513// This is similar to CopyTexImageTestES3.CopyTexSubImageFromTexture3D but for GL_OES_texture_3D514// extension.515TEST_P(CopyTexImageTest, CopyTexSubImageFrom3DTexureOES)516{517ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_3D"));518// TODO(anglebug.com/3801)519// Seems to fail on D3D11 Windows.520ANGLE_SKIP_TEST_IF(IsD3D11() & IsWindows());521522// http://anglebug.com/4927523ANGLE_SKIP_TEST_IF((IsPixel2() || IsNexus5X()) && IsOpenGLES());524525constexpr GLsizei kDepth = 6;526527// The framebuffer will be a slice of a 3d texture with a different colors for each slice. Each528// glCopyTexSubImage2D will take one face of this image to copy over a pixel in a 1x6529// framebuffer.530GLColor fboPixels[kDepth] = {GLColor::red, GLColor::yellow, GLColor::green,531GLColor::cyan, GLColor::blue, GLColor::magenta};532GLColor whitePixels[kDepth] = {GLColor::white, GLColor::white, GLColor::white,533GLColor::white, GLColor::white, GLColor::white};534535GLTexture fboTex;536glBindTexture(GL_TEXTURE_3D, fboTex);537glTexImage3DOES(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, kDepth, 0, GL_RGBA, GL_UNSIGNED_BYTE,538fboPixels);539540GLTexture dstTex;541glBindTexture(GL_TEXTURE_2D, dstTex);542glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kDepth, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, whitePixels);543544GLFramebuffer fbo;545glBindFramebuffer(GL_FRAMEBUFFER, fbo);546547for (GLsizei slice = 0; slice < kDepth; ++slice)548{549glFramebufferTexture3DOES(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, fboTex, 0,550slice);551552ASSERT_GL_NO_ERROR();553ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));554555// Copy the fbo (a 3d slice) into a pixel of the destination texture.556glCopyTexSubImage2D(GL_TEXTURE_2D, 0, slice, 0, 0, 0, 1, 1);557}558559// Make sure all the copies are done correctly.560glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTex, 0);561562ASSERT_GL_NO_ERROR();563ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));564565for (GLsizei slice = 0; slice < kDepth; ++slice)566{567EXPECT_PIXEL_COLOR_EQ(slice, 0, fboPixels[slice]);568}569}570571// specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3572// context573class CopyTexImageTestES3 : public CopyTexImageTest574{575protected:576void initialize3DTexture(GLTexture &texture,577const GLsizei imageWidth,578const GLsizei imageHeight,579const GLsizei imageDepth,580const GLColor *textureData);581void initialize2DTexture(GLTexture &texture,582const GLsizei imageWidth,583const GLsizei imageHeight,584const GLColor *textureData);585void initialize2DTextureUShort4444(GLTexture &texture,586const GLsizei imageWidth,587const GLsizei imageHeight,588const GLColor *textureData);589void fillTexture(std::vector<GLColor> &texture, const GLColor color);590void clearTexture(GLFramebuffer &fbo, GLTexture &texture, const GLColor color);591void copyTexSubImage3D(GLTexture &subTexture2D,592const GLint xOffset,593const GLint yOffset,594const GLsizei subImageWidth,595const GLsizei subImageHeight,596const GLsizei imageDepth);597void verifyCopyTexSubImage3D(GLTexture &texture3D,598const GLint xOffset,599const GLint yOffset,600const GLColor subImageColor);601602// Constants603const GLColor kSubImageColor = GLColor::yellow;604// 3D image dimensions605const GLsizei kImageWidth = getWindowWidth();606const GLsizei kImageHeight = getWindowHeight();607const GLsizei kImageDepth = 4;608// 2D sub-image dimensions609const GLsizei kSubImageWidth = getWindowWidth() / 4;610const GLsizei kSubImageHeight = getWindowHeight() / 4;611// Sub-Image Offsets612const GLint kXOffset = getWindowWidth() - kSubImageWidth;613const GLint kYOffset = getWindowHeight() - kSubImageHeight;614};615616// The test verifies that glCopyTexSubImage2D generates a GL_INVALID_OPERATION error617// when the read buffer is GL_NONE.618// Reference: GLES 3.0.4, Section 3.8.5 Alternate Texture Image Specification Commands619TEST_P(CopyTexImageTestES3, ReadBufferIsNone)620{621initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);622623GLTexture tex;624glBindTexture(GL_TEXTURE_2D, tex);625glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);626glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);627628glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);629glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kFboSizes[0], kFboSizes[0], 0);630631glReadBuffer(GL_NONE);632633EXPECT_GL_NO_ERROR();634glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 4, 4);635EXPECT_GL_ERROR(GL_INVALID_OPERATION);636}637638// Test CopyTexImage3D with some simple parameters with a 2D array texture.639TEST_P(CopyTexImageTestES3, 2DArraySubImage)640{641// Seems to fail on AMD OpenGL Windows.642ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() & IsWindows());643644GLTexture tex;645glBindTexture(GL_TEXTURE_2D_ARRAY, tex);646647constexpr GLsizei kTexSize = 4;648constexpr GLsizei kLayerOffset = 1;649constexpr GLsizei kLayers = 2;650651// Clear screen to green.652glClearColor(0, 1, 0, 1);653glClear(GL_COLOR_BUFFER_BIT);654655// Initialize a two-layer 2D array texture with red.656std::vector<GLColor> red(kTexSize * kTexSize * kLayers, GLColor::red);657glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, kTexSize, kTexSize, kLayers, 0, GL_RGBA,658GL_UNSIGNED_BYTE, red.data());659glCopyTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, kLayerOffset, 0, 0, kTexSize, kTexSize);660ASSERT_GL_NO_ERROR();661662// Check level 0 (red from image data) and 1 (green from backbuffer clear).663GLFramebuffer fbo;664glBindFramebuffer(GL_FRAMEBUFFER, fbo);665glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0);666EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);667glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);668for (int x = 0; x < kTexSize; x++)669{670for (int y = 0; y < kTexSize; y++)671{672EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);673}674}675ASSERT_GL_NO_ERROR();676}677678// Test if glCopyTexImage2D() implementation performs conversions well from GL_TEXTURE_3D to679// GL_TEXTURE_2D.680TEST_P(CopyTexImageTestES3, CopyTexSubImageFromTexture3D)681{682// TODO(anglebug.com/3801)683// Seems to fail on D3D11 Windows.684ANGLE_SKIP_TEST_IF(IsD3D11() & IsWindows());685686constexpr GLsizei kTexSize = 4;687constexpr GLsizei kLayers = 2;688std::vector<GLColor> red(kTexSize * kTexSize * kLayers, GLColor::red);689690GLFramebuffer fbo;691glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);692glBindTexture(GL_TEXTURE_2D, 0);693694// We will be reading from zeroth color attachment.695glReadBuffer(GL_COLOR_ATTACHMENT0);696697GLTexture src_object_id;698glBindTexture(GL_TEXTURE_3D, src_object_id);699glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, kTexSize, kTexSize, kLayers, 0, GL_RGBA,700GL_UNSIGNED_BYTE, NULL);701glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 1, kTexSize, kTexSize, 1, GL_RGBA, GL_UNSIGNED_BYTE,702red.data());703glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, src_object_id, 0, 1);704ASSERT_GL_NO_ERROR();705706GLTexture dst_object_id;707glBindTexture(GL_TEXTURE_2D, dst_object_id);708glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, kTexSize, kTexSize, 0);709glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_object_id,7100);711EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);712ASSERT_GL_NO_ERROR();713}714715// Test that copying from a non-zero base texture works.716TEST_P(CopyTexImageTestES3, CopyTexSubImageFromNonZeroBase)717{718// http://anglebug.com/5000719ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());720721constexpr GLsizei kTexSize = 4;722std::vector<GLColor> red(kTexSize * kTexSize, GLColor::red);723std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);724725// Create a framebuffer attached to a non-zero base texture726GLTexture srcColor;727glBindTexture(GL_TEXTURE_2D, srcColor);728glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,729red.data());730glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,731green.data());732glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);733ASSERT_GL_NO_ERROR();734735GLFramebuffer fbo;736glBindFramebuffer(GL_FRAMEBUFFER, fbo);737glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 1);738ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);739740// Create a texture with an identical format741GLTexture dstColor;742glBindTexture(GL_TEXTURE_2D, dstColor);743glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,744nullptr);745glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);746glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);747ASSERT_GL_NO_ERROR();748749// Copy into a part of this texture.750glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2);751ASSERT_GL_NO_ERROR();752753// Verify it.754constexpr std::array<GLubyte, 4> kExpected = {0, 255, 0, 255};755verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2);756757// Copy into another part of the texture. The previous verification ensures that the texture's758// internal image is allocated, so this should be a direct copy.759glBindFramebuffer(GL_FRAMEBUFFER, fbo);760glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kTexSize / 2, kTexSize / 2, 0, 0, kTexSize / 2,761kTexSize / 2);762ASSERT_GL_NO_ERROR();763764// Verify it.765verifyResults(dstColor, kExpected.data(), kTexSize, kTexSize / 2, kTexSize / 2, kTexSize,766kTexSize);767}768769// Test that copying into a non-zero base texture works.770TEST_P(CopyTexImageTestES3, CopyTexSubImageToNonZeroBase)771{772// http://anglebug.com/5000773ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());774775constexpr GLsizei kTexSize = 4;776std::vector<GLColor> green(kTexSize * kTexSize, GLColor::green);777778// Create a framebuffer attached to a non-zero base texture779GLTexture srcColor;780glBindTexture(GL_TEXTURE_2D, srcColor);781glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,782green.data());783ASSERT_GL_NO_ERROR();784785GLFramebuffer fbo;786glBindFramebuffer(GL_FRAMEBUFFER, fbo);787glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcColor, 0);788ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);789790// Create a texture with an identical format791GLTexture dstColor;792glBindTexture(GL_TEXTURE_2D, dstColor);793glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,794nullptr);795glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexSize, kTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,796nullptr);797glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);798glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);799glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);800glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);801ASSERT_GL_NO_ERROR();802803// Copy into a part of this texture.804glCopyTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 0, 0, kTexSize / 2, kTexSize / 2);805ASSERT_GL_NO_ERROR();806807// Verify it.808constexpr std::array<GLubyte, 4> kExpected = {0, 255, 0, 255};809verifyResults(dstColor, kExpected.data(), kTexSize, 0, 0, kTexSize / 2, kTexSize / 2);810811// Copy into another part of the texture. The previous verification ensures that the texture's812// internal image is allocated, so this should be a direct copy.813glBindFramebuffer(GL_FRAMEBUFFER, fbo);814glCopyTexSubImage2D(GL_TEXTURE_2D, 1, kTexSize / 2, kTexSize / 2, 0, 0, kTexSize / 2,815kTexSize / 2);816ASSERT_GL_NO_ERROR();817818// Verify it.819verifyResults(dstColor, kExpected.data(), kTexSize, kTexSize / 2, kTexSize / 2, kTexSize,820kTexSize);821}822823// Initialize the 3D texture we will copy the subImage data into824void CopyTexImageTestES3::initialize3DTexture(GLTexture &texture,825const GLsizei imageWidth,826const GLsizei imageHeight,827const GLsizei imageDepth,828const GLColor *textureData)829{830glBindTexture(GL_TEXTURE_3D, texture);831glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, imageWidth, imageHeight, imageDepth, 0, GL_RGBA,832GL_UNSIGNED_BYTE, textureData);833glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);834glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);835glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);836glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);837glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);838}839840void CopyTexImageTestES3::initialize2DTexture(GLTexture &texture,841const GLsizei imageWidth,842const GLsizei imageHeight,843const GLColor *textureData)844{845glBindTexture(GL_TEXTURE_2D, texture);846glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,847textureData);848glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);849glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);850}851852void CopyTexImageTestES3::initialize2DTextureUShort4444(GLTexture &texture,853const GLsizei imageWidth,854const GLsizei imageHeight,855const GLColor *textureData)856{857glBindTexture(GL_TEXTURE_2D, texture);858glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA,859GL_UNSIGNED_SHORT_4_4_4_4, textureData);860glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);861glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);862}863864void CopyTexImageTestES3::fillTexture(std::vector<GLColor> &texture, const GLColor color)865{866for (auto &texel : texture)867{868texel = color;869}870}871872void CopyTexImageTestES3::clearTexture(GLFramebuffer &fbo, GLTexture &texture, const GLColor color)873{874glBindFramebuffer(GL_FRAMEBUFFER, fbo);875glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);876ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));877glClearColor(color.R, color.G, color.B, color.A);878glClear(GL_COLOR_BUFFER_BIT);879EXPECT_PIXEL_COLOR_EQ(0, 0, color);880}881882void CopyTexImageTestES3::copyTexSubImage3D(GLTexture &subTexture2D,883const GLint xOffset,884const GLint yOffset,885const GLsizei subImageWidth,886const GLsizei subImageHeight,887const GLsizei imageDepth)888{889// Copy the 2D sub-image into the 3D texture890for (int currLayer = 0; currLayer < imageDepth; ++currLayer)891{892// Bind the 2D texture to GL_COLOR_ATTACHMENT0893glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,894subTexture2D, 0);895ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));896glCopyTexSubImage3D(GL_TEXTURE_3D, 0, xOffset, yOffset, currLayer, 0, 0, subImageWidth,897subImageHeight);898ASSERT_GL_NO_ERROR();899}900}901902void CopyTexImageTestES3::verifyCopyTexSubImage3D(GLTexture &texture3D,903const GLint xOffset,904const GLint yOffset,905const GLColor subImageColor)906{907// Bind to an FBO to check the copy was successful908for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)909{910glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, currLayer);911ASSERT_GL_NO_ERROR();912EXPECT_PIXEL_COLOR_EQ(xOffset, yOffset, subImageColor);913}914}915916// Test glCopyTexSubImage3D with initialized texture data917TEST_P(CopyTexImageTestES3, 3DSubImageRawTextureData)918{919// Texture data920std::vector<GLColor> textureData(kImageWidth * kImageHeight * kImageDepth);921922// Fill the textures with color923fillTexture(textureData, GLColor::red);924925GLFramebuffer fbo;926glBindFramebuffer(GL_FRAMEBUFFER, fbo);927928GLTexture texture3D;929initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, textureData.data());930931// The 2D texture that will be the sub-image copied into the destination texture932GLTexture subTexture2D;933initialize2DTexture(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);934clearTexture(fbo, subTexture2D, kSubImageColor);935936// Copy the 2D subimage into the 3D texture937copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,938kImageDepth);939940// Verify the color wasn't overwritten941verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::red);942// Verify the copy succeeded943verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);944945glBindFramebuffer(GL_FRAMEBUFFER, 0);946glBindTexture(GL_TEXTURE_2D, 0);947glBindTexture(GL_TEXTURE_3D, 0);948}949950// Test glCopyTexSubImage3D with initialized texture data that was drawn to951TEST_P(CopyTexImageTestES3, 3DSubImageDrawTextureData)952{953// TODO(anglebug.com/3801)954ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());955956GLFramebuffer fbo;957glBindFramebuffer(GL_FRAMEBUFFER, fbo);958959// The 3D texture we will copy the sub-image into960GLTexture texture3D;961initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, nullptr);962963// Draw to each layer in the 3D texture964for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)965{966ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());967glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0,968currLayer);969glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0,970currLayer);971ASSERT_GL_NO_ERROR();972glUseProgram(greenProgram);973drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);974ASSERT_GL_NO_ERROR();975EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);976}977978// The 2D texture that will be the sub-image copied into the destination texture979GLTexture subTexture2D;980initialize2DTexture(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);981clearTexture(fbo, subTexture2D, kSubImageColor);982983// Copy the 2D sub-image into the 3D texture984copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,985kImageDepth);986987// Verify the color wasn't overwritten988verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::green);989// Verify the copy succeeded990verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);991992glBindFramebuffer(GL_FRAMEBUFFER, 0);993glBindTexture(GL_TEXTURE_2D, 0);994glBindTexture(GL_TEXTURE_3D, 0);995}996997// Test glCopyTexSubImage3D with mismatched texture formats998TEST_P(CopyTexImageTestES3, 3DSubImageDrawMismatchedTextureTypes)999{1000// TODO(anglebug.com/3801)1001ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());10021003// TODO(anglebug.com/5491)1004ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());10051006GLFramebuffer fbo;1007glBindFramebuffer(GL_FRAMEBUFFER, fbo);10081009// The 3D texture we will copy the sub-image into1010GLTexture texture3D;1011initialize3DTexture(texture3D, kImageWidth, kImageHeight, kImageDepth, nullptr);10121013// Draw to each layer in the 3D texture1014for (int currLayer = 0; currLayer < kImageDepth; ++currLayer)1015{1016ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());1017glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture3D, 0, currLayer);1018ASSERT_GL_NO_ERROR();1019glUseProgram(greenProgram);1020drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);1021ASSERT_GL_NO_ERROR();1022EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);1023}10241025// The 2D texture that will be the sub-image copied into the destination texture1026GLTexture subTexture2D;1027initialize2DTextureUShort4444(subTexture2D, kSubImageWidth, kSubImageHeight, nullptr);1028clearTexture(fbo, subTexture2D, kSubImageColor);10291030// Copy the 2D sub-image into the 3D texture1031copyTexSubImage3D(subTexture2D, kXOffset, kYOffset, kSubImageWidth, kSubImageHeight,1032kImageDepth);10331034// Verify the color wasn't overwritten1035verifyCopyTexSubImage3D(texture3D, 0, 0, GLColor::green);1036// Verify the copy succeeded1037verifyCopyTexSubImage3D(texture3D, kXOffset, kYOffset, kSubImageColor);10381039glBindFramebuffer(GL_FRAMEBUFFER, 0);1040glBindTexture(GL_TEXTURE_2D, 0);1041glBindTexture(GL_TEXTURE_3D, 0);1042}10431044ANGLE_INSTANTIATE_TEST(CopyTexImageTest,1045ANGLE_ALL_TEST_PLATFORMS_ES2,1046ES2_D3D11_PRESENT_PATH_FAST(),1047ES3_VULKAN(),1048WithEmulateCopyTexImage2DFromRenderbuffers(ES2_OPENGL()),1049WithEmulateCopyTexImage2DFromRenderbuffers(ES2_OPENGLES()));10501051GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyTexImageTestES3);1052ANGLE_INSTANTIATE_TEST(CopyTexImageTestES3,1053ANGLE_ALL_TEST_PLATFORMS_ES3,1054WithEmulateCopyTexImage2DFromRenderbuffers(ES3_OPENGL()),1055WithEmulateCopyTexImage2DFromRenderbuffers(ES3_OPENGLES()));1056} // namespace angle105710581059