gl_copy_texture_CHROMIUM_unittest.cc 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef GL_GLEXT_PROTOTYPES
  5. #define GL_GLEXT_PROTOTYPES
  6. #endif
  7. #include <GLES2/gl2.h>
  8. #include <GLES2/gl2ext.h>
  9. #include <GLES2/gl2extchromium.h>
  10. #include <GLES3/gl3.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include "base/logging.h"
  14. #include "build/build_config.h"
  15. #include "gpu/command_buffer/tests/gl_manager.h"
  16. #include "gpu/command_buffer/tests/gl_test_utils.h"
  17. #include "testing/gmock/include/gmock/gmock.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. #include "ui/gl/gl_enums.h"
  20. #include "ui/gl/gl_version_info.h"
  21. namespace gpu {
  22. namespace {
  23. enum CopyType { TexImage, TexSubImage };
  24. const CopyType kCopyTypes[] = {
  25. TexImage,
  26. TexSubImage,
  27. };
  28. struct FormatType {
  29. GLenum internal_format;
  30. GLenum format;
  31. GLenum type;
  32. };
  33. static const char* kSimpleVertexShaderES2 =
  34. "attribute vec2 a_position;\n"
  35. "varying vec2 v_texCoord;\n"
  36. "void main() {\n"
  37. " gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);\n"
  38. " v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5;\n"
  39. "}\n";
  40. static const char* kSimpleVertexShaderES3 =
  41. "#version 300 es\n"
  42. "in vec2 a_position;\n"
  43. "out vec2 v_texCoord;\n"
  44. "void main() {\n"
  45. " gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);\n"
  46. " v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5;\n"
  47. "}\n";
  48. std::string GetFragmentShaderSource(GLenum target, GLenum format, bool is_es3) {
  49. std::string source;
  50. if (is_es3) {
  51. source +=
  52. "#version 300 es\n"
  53. "#define VARYING in\n"
  54. "#define FRAGCOLOR frag_color\n"
  55. "#define TextureLookup texture\n";
  56. } else {
  57. source +=
  58. "#define VARYING varying\n"
  59. "#define FRAGCOLOR gl_FragColor\n";
  60. if (target == GL_TEXTURE_CUBE_MAP) {
  61. source += "#define TextureLookup textureCube\n";
  62. } else {
  63. source += "#define TextureLookup texture2D\n";
  64. }
  65. }
  66. source += "precision mediump float;\n";
  67. if (gles2::GLES2Util::IsSignedIntegerFormat(format)) {
  68. if (target == GL_TEXTURE_CUBE_MAP) {
  69. source += "#define SamplerType isamplerCube\n";
  70. } else {
  71. source += "#define SamplerType isampler2D\n";
  72. }
  73. source += "#define TextureType ivec4\n";
  74. source += "#define ScaleValue 255.0\n";
  75. } else if (gles2::GLES2Util::IsUnsignedIntegerFormat(format)) {
  76. if (target == GL_TEXTURE_CUBE_MAP) {
  77. source += "#define SamplerType usamplerCube\n";
  78. } else {
  79. source += "#define SamplerType usampler2D\n";
  80. }
  81. source += "#define TextureType uvec4\n";
  82. source += "#define ScaleValue 255.0\n";
  83. } else {
  84. if (target == GL_TEXTURE_CUBE_MAP) {
  85. source += "#define SamplerType samplerCube\n";
  86. } else {
  87. source += "#define SamplerType sampler2D\n";
  88. }
  89. source += "#define TextureType vec4\n";
  90. source += "#define ScaleValue 1.0\n";
  91. }
  92. if (is_es3)
  93. source += "out vec4 frag_color;\n";
  94. if (target == GL_TEXTURE_CUBE_MAP)
  95. source += "uniform highp int u_face;\n";
  96. source +=
  97. "uniform mediump SamplerType u_texture;\n"
  98. "VARYING vec2 v_texCoord;\n"
  99. "void main() {\n";
  100. if (target == GL_TEXTURE_CUBE_MAP) {
  101. source +=
  102. " vec3 texCube;\n"
  103. // Transform [0, 1] to [-1, 1].
  104. " vec2 texCoord = (v_texCoord * 2.0) - 1.0;\n"
  105. // Transform 2d tex coord to each face of TEXTURE_CUBE_MAP coord.
  106. // TEXTURE_CUBE_MAP_POSITIVE_X
  107. " if (u_face == 34069) {\n"
  108. " texCube = vec3(1.0, -texCoord.y, -texCoord.x);\n"
  109. // TEXTURE_CUBE_MAP_NEGATIVE_X
  110. " } else if (u_face == 34070) {\n"
  111. " texCube = vec3(-1.0, -texCoord.y, texCoord.x);\n"
  112. // TEXTURE_CUBE_MAP_POSITIVE_Y
  113. " } else if (u_face == 34071) {\n"
  114. " texCube = vec3(texCoord.x, 1.0, texCoord.y);\n"
  115. // TEXTURE_CUBE_MAP_NEGATIVE_Y
  116. " } else if (u_face == 34072) {\n"
  117. " texCube = vec3(texCoord.x, -1.0, -texCoord.y);\n"
  118. // TEXTURE_CUBE_MAP_POSITIVE_Z
  119. " } else if (u_face == 34073) {\n"
  120. " texCube = vec3(texCoord.x, -texCoord.y, 1.0);\n"
  121. // TEXTURE_CUBE_MAP_NEGATIVE_Z
  122. " } else if (u_face == 34074) {\n"
  123. " texCube = vec3(-texCoord.x, -texCoord.y, -1.0);\n"
  124. " }\n"
  125. " TextureType color = TextureLookup(u_texture, texCube);\n";
  126. } else {
  127. source += " TextureType color = TextureLookup(u_texture, v_texCoord);\n";
  128. }
  129. source +=
  130. " FRAGCOLOR = vec4(color) / ScaleValue;\n"
  131. "}\n";
  132. return source;
  133. }
  134. void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t* color) {
  135. color[0] = r;
  136. color[1] = g;
  137. color[2] = b;
  138. color[3] = a;
  139. }
  140. void getExpectedColorAndMask(GLenum src_internal_format,
  141. GLenum dest_internal_format,
  142. const uint8_t* color,
  143. uint8_t* expected_color,
  144. uint8_t* expected_mask) {
  145. uint8_t adjusted_color[4];
  146. switch (src_internal_format) {
  147. case GL_ALPHA:
  148. setColor(0, 0, 0, color[0], adjusted_color);
  149. break;
  150. case GL_R8:
  151. case GL_R16_EXT:
  152. setColor(color[0], 0, 0, 255, adjusted_color);
  153. break;
  154. case GL_LUMINANCE:
  155. setColor(color[0], color[0], color[0], 255, adjusted_color);
  156. break;
  157. case GL_LUMINANCE_ALPHA:
  158. setColor(color[0], color[0], color[0], color[1], adjusted_color);
  159. break;
  160. case GL_RG16_EXT:
  161. setColor(color[0], color[1], 0, 255, adjusted_color);
  162. break;
  163. case GL_RGB:
  164. case GL_RGB8:
  165. case GL_RGB_YCBCR_420V_CHROMIUM:
  166. case GL_RGB_YCBCR_422_CHROMIUM:
  167. setColor(color[0], color[1], color[2], 255, adjusted_color);
  168. break;
  169. case GL_RGBA:
  170. case GL_RGBA8:
  171. case GL_RGBA16_EXT:
  172. setColor(color[0], color[1], color[2], color[3], adjusted_color);
  173. break;
  174. case GL_BGRA_EXT:
  175. case GL_BGRA8_EXT:
  176. setColor(color[2], color[1], color[0], color[3], adjusted_color);
  177. break;
  178. case GL_RGB10_A2: {
  179. // Map the source 2-bit Alpha to 8-bits.
  180. const uint8_t alpha_value = (color[3] & 0x3) * 255 / 3;
  181. setColor(color[0] >> 2, color[1] >> 2, color[2] >> 2, alpha_value,
  182. adjusted_color);
  183. break;
  184. }
  185. default:
  186. NOTREACHED() << gl::GLEnums::GetStringEnum(src_internal_format);
  187. break;
  188. }
  189. switch (dest_internal_format) {
  190. // TODO(crbug.com/577144): Enable GL_ALPHA, GL_LUMINANCE and
  191. // GL_LUMINANCE_ALPHA.
  192. case GL_R8:
  193. case GL_R16F:
  194. case GL_R32F:
  195. case GL_R8UI:
  196. setColor(adjusted_color[0], 0, 0, 0, expected_color);
  197. setColor(1, 0, 0, 0, expected_mask);
  198. break;
  199. case GL_RG8:
  200. case GL_RG16F:
  201. case GL_RG32F:
  202. case GL_RG8UI:
  203. setColor(adjusted_color[0], adjusted_color[1], 0, 0, expected_color);
  204. setColor(1, 1, 0, 0, expected_mask);
  205. break;
  206. case GL_RGB:
  207. case GL_RGB8:
  208. case GL_SRGB_EXT:
  209. case GL_SRGB8:
  210. case GL_RGB565:
  211. case GL_R11F_G11F_B10F:
  212. case GL_RGB9_E5:
  213. case GL_RGB16F:
  214. case GL_RGB32F:
  215. case GL_RGB8UI:
  216. setColor(adjusted_color[0], adjusted_color[1], adjusted_color[2], 0,
  217. expected_color);
  218. setColor(1, 1, 1, 0, expected_mask);
  219. break;
  220. case GL_RGBA:
  221. case GL_RGBA8:
  222. case GL_BGRA_EXT:
  223. case GL_BGRA8_EXT:
  224. case GL_SRGB_ALPHA_EXT:
  225. case GL_SRGB8_ALPHA8:
  226. case GL_RGBA4:
  227. case GL_RGBA16F:
  228. case GL_RGBA32F:
  229. case GL_RGBA8UI:
  230. setColor(adjusted_color[0], adjusted_color[1], adjusted_color[2],
  231. adjusted_color[3], expected_color);
  232. setColor(1, 1, 1, 1, expected_mask);
  233. break;
  234. case GL_RGB10_A2: {
  235. // Map the 2-bit Alpha values back to full bytes.
  236. constexpr uint8_t step = 0x55;
  237. const uint8_t alpha_value = (adjusted_color[3] + step / 2) / step * step;
  238. setColor(adjusted_color[0], adjusted_color[1], adjusted_color[2],
  239. alpha_value, expected_color);
  240. #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  241. // The alpha channel values for LUMINANCE_ALPHA source don't work OK
  242. // on Mac or Linux, so skip comparison of those, see crbug.com/926579
  243. setColor(1, 1, 1, src_internal_format != GL_LUMINANCE_ALPHA,
  244. expected_mask);
  245. #else
  246. setColor(1, 1, 1, 1, expected_mask);
  247. #endif
  248. break;
  249. }
  250. case GL_RGB5_A1:
  251. setColor(adjusted_color[0], adjusted_color[1], adjusted_color[2],
  252. (adjusted_color[3] >> 7) ? 0xFF : 0x0, expected_color);
  253. // TODO(qiankun.miao@intel.com): On some Windows platforms, the alpha
  254. // channel of expected color is the source alpha value other than 255.
  255. // This should be wrong. Skip the alpha channel check and revisit this in
  256. // future.
  257. setColor(1, 1, 1, 0, expected_mask);
  258. break;
  259. default:
  260. NOTREACHED() << gl::GLEnums::GetStringEnum(dest_internal_format);
  261. break;
  262. }
  263. }
  264. void getTextureDataAndExpectedRGBAs(FormatType src_format_type,
  265. FormatType dest_format_type,
  266. GLsizei width,
  267. GLsizei height,
  268. std::vector<uint8_t>* texture_data,
  269. std::vector<uint8_t>* expected_rgba_pixels,
  270. uint8_t* expected_mask) {
  271. DCHECK(texture_data);
  272. DCHECK(expected_rgba_pixels);
  273. const uint32_t src_channel_count = gles2::GLES2Util::ElementsPerGroup(
  274. src_format_type.format, src_format_type.type);
  275. constexpr uint8_t color[4] = {1u, 63u, 127u, 255u};
  276. uint8_t expected_color[4];
  277. constexpr uint8_t alt_color[4] = {200u, 100u, 0u, 255u};
  278. getExpectedColorAndMask(src_format_type.internal_format,
  279. dest_format_type.internal_format, color,
  280. expected_color, expected_mask);
  281. const size_t num_pixels = width * height;
  282. expected_rgba_pixels->resize(num_pixels * 4, 0);
  283. if (src_format_type.type == GL_UNSIGNED_BYTE) {
  284. uint8_t alt_expected_color[4];
  285. getExpectedColorAndMask(src_format_type.internal_format,
  286. dest_format_type.internal_format, alt_color,
  287. alt_expected_color, expected_mask);
  288. texture_data->resize(num_pixels * src_channel_count, 0);
  289. // Generate a simple diagonal pattern to be able to catch UV mapping errors.
  290. for (int y = 0; y < height; ++y) {
  291. for (int x = 0; x < width; ++x) {
  292. bool alt = !((y + x) % 11);
  293. for (uint32_t j = 0; j < 4; ++j) {
  294. if (j < src_channel_count) {
  295. texture_data->at((width * y + x) * src_channel_count + j) =
  296. (alt ? alt_color : color)[j];
  297. }
  298. expected_rgba_pixels->at((width * y + x) * 4 + j) =
  299. (alt ? alt_expected_color : expected_color)[j];
  300. }
  301. }
  302. }
  303. return;
  304. } else if (src_format_type.type == GL_UNSIGNED_SHORT) {
  305. constexpr uint16_t color_16bit[4] = {color[0] << 8, color[1] << 8,
  306. color[2] << 8, color[3] << 8};
  307. texture_data->resize(num_pixels * src_channel_count * sizeof(uint16_t));
  308. uint16_t* texture_data16 =
  309. reinterpret_cast<uint16_t*>(texture_data->data());
  310. int16_t flip_sign = -1;
  311. for (uint32_t i = 0; i < num_pixels * src_channel_count;
  312. i += src_channel_count) {
  313. for (uint32_t j = 0; j < src_channel_count; ++j) {
  314. // Introduce an offset to the value to check. Expected value should be
  315. // the same as without the offset.
  316. flip_sign *= -1;
  317. int16_t offset = flip_sign * ((i + j) % 0x7F);
  318. texture_data16[i + j] = color_16bit[j] + offset;
  319. }
  320. }
  321. for (uint32_t i = 0; i < num_pixels * 4; i += 4) {
  322. for (int c = 0; c < 4; ++c) {
  323. expected_rgba_pixels->at(i + c) = expected_color[c];
  324. }
  325. }
  326. return;
  327. } else if (src_format_type.type == GL_UNSIGNED_INT_2_10_10_10_REV) {
  328. DCHECK_EQ(src_channel_count, 1u);
  329. constexpr uint32_t color_rgb10_a2 = ((color[3] & 0x3) << 30) +
  330. (color[2] << 20) + (color[1] << 10) +
  331. color[0];
  332. texture_data->resize(num_pixels * sizeof(uint32_t));
  333. uint32_t* texture_data32 =
  334. reinterpret_cast<uint32_t*>(texture_data->data());
  335. for (uint32_t p = 0; p < num_pixels; ++p) {
  336. texture_data32[p] = color_rgb10_a2;
  337. memcpy(expected_rgba_pixels->data() + p * 4, expected_color, 4);
  338. }
  339. return;
  340. }
  341. NOTREACHED() << gl::GLEnums::GetStringEnum(src_format_type.type);
  342. return;
  343. }
  344. } // namespace
  345. // A collection of tests that exercise the GL_CHROMIUM_copy_texture extension.
  346. class GLCopyTextureCHROMIUMTest
  347. : public testing::Test,
  348. public ::testing::WithParamInterface<CopyType> {
  349. protected:
  350. void CreateAndBindDestinationTextureAndFBO(GLenum target) {
  351. glGenTextures(2, textures_);
  352. glBindTexture(target, textures_[1]);
  353. // Some drivers (NVidia/SGX) require texture settings to be a certain way or
  354. // they won't report FRAMEBUFFER_COMPLETE.
  355. glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  356. glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  357. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  358. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  359. glGenFramebuffers(1, &framebuffer_id_);
  360. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id_);
  361. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
  362. textures_[1], 0);
  363. }
  364. void SetUp() override {
  365. GLManager::Options options;
  366. options.size = gfx::Size(64, 64);
  367. gl_.Initialize(options);
  368. width_ = 8;
  369. height_ = 8;
  370. }
  371. void TearDown() override { gl_.Destroy(); }
  372. GLuint CreateDrawingTexture(GLenum target, GLsizei width, GLsizei height) {
  373. GLuint texture = 0;
  374. glGenTextures(1, &texture);
  375. glBindTexture(target, texture);
  376. glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  377. glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  378. glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_RGBA,
  379. GL_UNSIGNED_BYTE, nullptr);
  380. return texture;
  381. }
  382. GLuint CreateDrawingFBO(GLenum target, GLuint texture) {
  383. GLuint framebuffer = 0;
  384. glGenFramebuffers(1, &framebuffer);
  385. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
  386. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
  387. texture, 0);
  388. return framebuffer;
  389. }
  390. GLenum ExtractFormatFrom(GLenum internalformat) {
  391. switch (internalformat) {
  392. case GL_RGBA8_OES:
  393. return GL_RGBA;
  394. case GL_RGB8_OES:
  395. return GL_RGB;
  396. case GL_BGRA8_EXT:
  397. return GL_BGRA_EXT;
  398. default:
  399. NOTREACHED();
  400. return GL_NONE;
  401. }
  402. }
  403. void RunCopyTexture(GLenum dest_target,
  404. CopyType copy_type,
  405. FormatType src_format_type,
  406. GLint source_level,
  407. FormatType dest_format_type,
  408. GLint dest_level,
  409. bool is_es3) {
  410. std::vector<uint8_t> expected_pixels;
  411. std::vector<uint8_t> texture_data;
  412. uint8_t mask[4];
  413. getTextureDataAndExpectedRGBAs(src_format_type, dest_format_type, width_,
  414. height_, &texture_data, &expected_pixels,
  415. mask);
  416. GLenum source_target = GL_TEXTURE_2D;
  417. glGenTextures(2, textures_);
  418. glBindTexture(source_target, textures_[0]);
  419. glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  420. glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  421. #if BUILDFLAG(IS_MAC)
  422. // TODO(qiankun.miao@intel.com): Remove this workaround for Mac OSX, once
  423. // integer texture rendering bug is fixed on Mac OSX: crbug.com/679639.
  424. glTexImage2D(source_target, 0, src_format_type.internal_format,
  425. width_ << source_level, height_ << source_level, 0,
  426. src_format_type.format, src_format_type.type, nullptr);
  427. #endif
  428. glTexImage2D(source_target, source_level, src_format_type.internal_format,
  429. width_, height_, 0, src_format_type.format,
  430. src_format_type.type, texture_data.data());
  431. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  432. GLenum dest_binding_target =
  433. gles2::GLES2Util::GLFaceTargetToTextureTarget(dest_target);
  434. glBindTexture(dest_binding_target, textures_[1]);
  435. glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  436. glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  437. glTexParameteri(dest_binding_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  438. // This hack makes dest texture complete in ES2 and ES3 context
  439. // respectively. With this, sampling from the dest texture is correct.
  440. if (is_es3) {
  441. glTexParameteri(dest_binding_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  442. glTexParameteri(dest_binding_target, GL_TEXTURE_BASE_LEVEL, dest_level);
  443. // For cube map textures, make the texture cube complete.
  444. if (dest_binding_target == GL_TEXTURE_CUBE_MAP) {
  445. for (int i = 0; i < 6; ++i) {
  446. GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
  447. glTexImage2D(face, dest_level, dest_format_type.internal_format,
  448. width_, height_, 0, dest_format_type.format,
  449. dest_format_type.type, nullptr);
  450. }
  451. }
  452. #if BUILDFLAG(IS_MAC)
  453. // TODO(qiankun.miao@intel.com): Remove this workaround for Mac OSX, once
  454. // framebuffer complete bug is fixed on Mac OSX: crbug.com/678526.
  455. glTexImage2D(dest_target, 0, dest_format_type.internal_format,
  456. width_ << dest_level, height_ << dest_level, 0,
  457. dest_format_type.format, dest_format_type.type, nullptr);
  458. #endif
  459. } else {
  460. glTexParameteri(dest_binding_target, GL_TEXTURE_MIN_FILTER,
  461. GL_NEAREST_MIPMAP_NEAREST);
  462. // For cube map textures, make the texture cube complete.
  463. if (dest_binding_target == GL_TEXTURE_CUBE_MAP) {
  464. for (int i = 0; i < 6; ++i) {
  465. GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
  466. glTexImage2D(face, 0, dest_format_type.internal_format,
  467. width_ << dest_level, height_ << dest_level, 0,
  468. dest_format_type.format, dest_format_type.type, nullptr);
  469. }
  470. } else {
  471. glTexImage2D(dest_target, 0, dest_format_type.internal_format,
  472. width_ << dest_level, height_ << dest_level, 0,
  473. dest_format_type.format, dest_format_type.type, nullptr);
  474. }
  475. glGenerateMipmap(dest_binding_target);
  476. }
  477. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  478. if (copy_type == TexImage) {
  479. glCopyTextureCHROMIUM(textures_[0], source_level, dest_target,
  480. textures_[1], dest_level,
  481. dest_format_type.internal_format,
  482. dest_format_type.type, false, false, false);
  483. } else {
  484. glBindTexture(dest_binding_target, textures_[1]);
  485. glTexImage2D(dest_target, dest_level, dest_format_type.internal_format,
  486. width_, height_, 0, dest_format_type.format,
  487. dest_format_type.type, nullptr);
  488. // Split large blits into two in order to expose bugs at lower levels.
  489. constexpr int sub_rect_width = 8;
  490. if (width_ <= sub_rect_width) {
  491. glCopySubTextureCHROMIUM(textures_[0], source_level, dest_target,
  492. textures_[1], dest_level, 0, 0, 0, 0, width_,
  493. height_, false, false, false);
  494. } else {
  495. glCopySubTextureCHROMIUM(
  496. textures_[0], source_level, dest_target, textures_[1], dest_level,
  497. 0, 0, 0, 0, width_ - sub_rect_width, height_, false, false, false);
  498. glCopySubTextureCHROMIUM(
  499. textures_[0], source_level, dest_target, textures_[1], dest_level,
  500. width_ - sub_rect_width, 0, width_ - sub_rect_width, 0,
  501. sub_rect_width, height_, false, false, false);
  502. }
  503. }
  504. const GLenum last_error = glGetError();
  505. EXPECT_TRUE(last_error == GL_NO_ERROR)
  506. << gl::GLEnums::GetStringError(last_error);
  507. // Draw destination texture to a fbo with a TEXTURE_2D texture attachment
  508. // in RGBA format.
  509. GLuint texture = CreateDrawingTexture(GL_TEXTURE_2D, width_, height_);
  510. GLuint framebuffer = CreateDrawingFBO(GL_TEXTURE_2D, texture);
  511. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  512. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  513. glViewport(0, 0, width_, height_);
  514. glBindTexture(dest_binding_target, textures_[1]);
  515. std::string fragment_shader_source = GetFragmentShaderSource(
  516. dest_binding_target, dest_format_type.internal_format, is_es3);
  517. GLTestHelper::DrawTextureQuad(
  518. dest_target, is_es3 ? kSimpleVertexShaderES3 : kSimpleVertexShaderES2,
  519. fragment_shader_source.c_str(), "a_position", "u_texture", "u_face");
  520. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  521. uint8_t tolerance = dest_format_type.internal_format == GL_RGBA4 ? 20 : 7;
  522. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, width_, height_, tolerance,
  523. expected_pixels, mask))
  524. << " dest_target : " << gles2::GLES2Util::GetStringEnum(dest_target)
  525. << " src_internal_format: "
  526. << gles2::GLES2Util::GetStringEnum(src_format_type.internal_format)
  527. << " source_level: " << source_level << " dest_internal_format: "
  528. << gles2::GLES2Util::GetStringEnum(dest_format_type.internal_format)
  529. << " dest_level: " << dest_level;
  530. glDeleteTextures(1, &texture);
  531. glDeleteFramebuffers(1, &framebuffer);
  532. glDeleteTextures(2, textures_);
  533. }
  534. GLManager gl_;
  535. GLuint textures_[2];
  536. GLsizei width_;
  537. GLsizei height_;
  538. GLuint framebuffer_id_;
  539. };
  540. class GLCopyTextureCHROMIUMES3Test : public GLCopyTextureCHROMIUMTest {
  541. protected:
  542. void SetUp() override {
  543. GLManager::Options options;
  544. options.context_type = CONTEXT_TYPE_OPENGLES3;
  545. options.size = gfx::Size(64, 64);
  546. gl_.Initialize(options);
  547. width_ = 8;
  548. height_ = 8;
  549. }
  550. // If a driver isn't capable of supporting ES3 context, creating
  551. // ContextGroup will fail. Just skip the test.
  552. bool ShouldSkipTest() const {
  553. return (!gl_.decoder() || !gl_.decoder()->GetContextGroup());
  554. }
  555. // If EXT_color_buffer_float isn't available, float format isn't supported.
  556. bool ShouldSkipFloatFormat() const {
  557. DCHECK(!ShouldSkipTest());
  558. return !gl_.decoder()->GetFeatureInfo()->ext_color_buffer_float_available();
  559. }
  560. bool ShouldSkipBGRA() const {
  561. DCHECK(!ShouldSkipTest());
  562. return !gl_.decoder()
  563. ->GetFeatureInfo()
  564. ->feature_flags()
  565. .ext_texture_format_bgra8888;
  566. }
  567. bool ShouldSkipSRGBEXT() const {
  568. DCHECK(!ShouldSkipTest());
  569. return !gl_.decoder()->GetFeatureInfo()->feature_flags().ext_srgb;
  570. }
  571. bool ShouldSkipNorm16() const {
  572. DCHECK(!ShouldSkipTest());
  573. #if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || \
  574. BUILDFLAG(IS_CHROMEOS)) && \
  575. (defined(ARCH_CPU_X86) || defined(ARCH_CPU_X86_64))
  576. // Make sure it's tested; it is safe to assume that the flag is always true
  577. // on desktop.
  578. EXPECT_TRUE(
  579. gl_.decoder()->GetFeatureInfo()->feature_flags().ext_texture_norm16);
  580. #endif
  581. return !gl_.decoder()->GetFeatureInfo()->feature_flags().ext_texture_norm16;
  582. }
  583. bool ShouldSkipRGBA16ToRGB10A2() const {
  584. DCHECK(!ShouldSkipTest());
  585. #if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
  586. (defined(ARCH_CPU_X86) || defined(ARCH_CPU_X86_64))
  587. // // TODO(crbug.com/1046873): Fails on mac and linux intel.
  588. return true;
  589. #else
  590. return false;
  591. #endif
  592. }
  593. bool ShouldSkipRGB10A2() const {
  594. DCHECK(!ShouldSkipTest());
  595. const gl::GLVersionInfo& gl_version_info =
  596. gl_.decoder()->GetFeatureInfo()->gl_version_info();
  597. // XB30 support was introduced in GLES 3.0/ OpenGL 3.3, before that it was
  598. // signalled via a specific extension.
  599. const bool supports_rgb10_a2 =
  600. gl_version_info.IsAtLeastGL(3, 3) ||
  601. gl_version_info.IsAtLeastGLES(3, 0) ||
  602. GLTestHelper::HasExtension("GL_EXT_texture_type_2_10_10_10_REV");
  603. EXPECT_TRUE(supports_rgb10_a2);
  604. return !supports_rgb10_a2;
  605. }
  606. bool IsMacArm64() const {
  607. DCHECK(!ShouldSkipTest());
  608. #if BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM_FAMILY)
  609. return true;
  610. #else
  611. return false;
  612. #endif
  613. }
  614. bool IsMac() const {
  615. #if BUILDFLAG(IS_MAC)
  616. return true;
  617. #else
  618. return false;
  619. #endif
  620. }
  621. };
  622. INSTANTIATE_TEST_SUITE_P(CopyType,
  623. GLCopyTextureCHROMIUMTest,
  624. ::testing::ValuesIn(kCopyTypes));
  625. INSTANTIATE_TEST_SUITE_P(CopyType,
  626. GLCopyTextureCHROMIUMES3Test,
  627. ::testing::ValuesIn(kCopyTypes));
  628. // Test to ensure that the basic functionality of the extension works.
  629. TEST_P(GLCopyTextureCHROMIUMTest, Basic) {
  630. CopyType copy_type = GetParam();
  631. uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u};
  632. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  633. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  634. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  635. pixels);
  636. if (copy_type == TexImage) {
  637. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  638. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  639. } else {
  640. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  641. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  642. nullptr);
  643. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  644. 0, 0, 0, 1, 1, false, false, false);
  645. }
  646. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  647. // Check the FB is still bound.
  648. GLint value = 0;
  649. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
  650. GLuint fb_id = value;
  651. EXPECT_EQ(framebuffer_id_, fb_id);
  652. // Check that FB is complete.
  653. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  654. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  655. GLTestHelper::CheckPixels(0, 0, 1, 1, 0, pixels, nullptr);
  656. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  657. }
  658. TEST_P(GLCopyTextureCHROMIUMES3Test, BigTexture) {
  659. if (ShouldSkipTest() || ShouldSkipBGRA())
  660. return;
  661. width_ = 1080;
  662. height_ = 1080;
  663. const CopyType copy_type = GetParam();
  664. FormatType src_format{GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE};
  665. FormatType dest_format{GL_RGB, GL_RGB, GL_UNSIGNED_BYTE};
  666. RunCopyTexture(GL_TEXTURE_2D, copy_type, src_format, 0, dest_format, 0, true);
  667. }
  668. TEST_P(GLCopyTextureCHROMIUMES3Test, FormatCombinations) {
  669. if (ShouldSkipTest())
  670. return;
  671. if (IsMacArm64()) {
  672. LOG(INFO) << "TODO(crbug.com/1135372): fails on Apple DTK. Skipping.";
  673. return;
  674. }
  675. if (gl_.gpu_preferences().use_passthrough_cmd_decoder) {
  676. // TODO(geofflang): anglebug.com/1932
  677. LOG(INFO)
  678. << "Passthrough command decoder expected failure. Skipping test...";
  679. return;
  680. }
  681. if (IsMac() && !gl_.gpu_preferences().use_passthrough_cmd_decoder) {
  682. // TODO(crbug.com/1227853): Remove this suppression once this passes on Mac
  683. // 11.
  684. LOG(INFO) << "Validating decoder on Mac. Skipping.";
  685. return;
  686. }
  687. const CopyType copy_type = GetParam();
  688. FormatType src_format_types[] = {
  689. {GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE},
  690. {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
  691. {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE},
  692. {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
  693. {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
  694. {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
  695. {GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},
  696. {GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},
  697. {GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT},
  698. {GL_RG16_EXT, GL_RG, GL_UNSIGNED_SHORT},
  699. {GL_RGBA16_EXT, GL_RGBA, GL_UNSIGNED_SHORT},
  700. {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV},
  701. };
  702. FormatType dest_format_types[] = {
  703. // TODO(qiankun.miao@intel.com): ALPHA and LUMINANCE formats have bug on
  704. // GL core profile. See crbug.com/577144. Enable these formats after
  705. // using workaround in gles2_cmd_copy_tex_image.cc.
  706. // {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE},
  707. // {GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE},
  708. // {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
  709. {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE},
  710. {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
  711. {GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE},
  712. {GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE},
  713. {GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},
  714. {GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},
  715. {GL_R8, GL_RED, GL_UNSIGNED_BYTE},
  716. {GL_R16F, GL_RED, GL_HALF_FLOAT},
  717. {GL_R16F, GL_RED, GL_FLOAT},
  718. {GL_R32F, GL_RED, GL_FLOAT},
  719. {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE},
  720. {GL_RG8, GL_RG, GL_UNSIGNED_BYTE},
  721. {GL_RG16F, GL_RG, GL_HALF_FLOAT},
  722. {GL_RG16F, GL_RG, GL_FLOAT},
  723. {GL_RG32F, GL_RG, GL_FLOAT},
  724. {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE},
  725. {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
  726. {GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE},
  727. {GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE},
  728. {GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT},
  729. {GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT},
  730. {GL_RGB9_E5, GL_RGB, GL_FLOAT},
  731. {GL_RGB16F, GL_RGB, GL_HALF_FLOAT},
  732. {GL_RGB16F, GL_RGB, GL_FLOAT},
  733. {GL_RGB32F, GL_RGB, GL_FLOAT},
  734. {GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE},
  735. {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
  736. {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE},
  737. {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE},
  738. {GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE},
  739. {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT},
  740. {GL_RGBA16F, GL_RGBA, GL_FLOAT},
  741. {GL_RGBA32F, GL_RGBA, GL_FLOAT},
  742. {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE},
  743. {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV},
  744. };
  745. for (auto src_format_type : src_format_types) {
  746. for (auto dest_format_type : dest_format_types) {
  747. if ((src_format_type.internal_format == GL_BGRA_EXT ||
  748. src_format_type.internal_format == GL_BGRA8_EXT ||
  749. dest_format_type.internal_format == GL_BGRA_EXT ||
  750. dest_format_type.internal_format == GL_BGRA8_EXT) &&
  751. ShouldSkipBGRA()) {
  752. continue;
  753. }
  754. if (gles2::GLES2Util::IsFloatFormat(dest_format_type.internal_format) &&
  755. ShouldSkipFloatFormat()) {
  756. continue;
  757. }
  758. if ((dest_format_type.internal_format == GL_SRGB_EXT ||
  759. dest_format_type.internal_format == GL_SRGB_ALPHA_EXT) &&
  760. ShouldSkipSRGBEXT()) {
  761. continue;
  762. }
  763. if ((src_format_type.internal_format == GL_R16_EXT ||
  764. src_format_type.internal_format == GL_RG16_EXT ||
  765. src_format_type.internal_format == GL_RGBA16_EXT) &&
  766. ShouldSkipNorm16())
  767. continue;
  768. if (src_format_type.internal_format == GL_RGB10_A2 && ShouldSkipRGB10A2())
  769. continue;
  770. if (src_format_type.internal_format == GL_RGBA16_EXT &&
  771. dest_format_type.internal_format == GL_RGB10_A2 &&
  772. ShouldSkipRGBA16ToRGB10A2())
  773. continue;
  774. RunCopyTexture(GL_TEXTURE_2D, copy_type, src_format_type, 0,
  775. dest_format_type, 0, true);
  776. }
  777. }
  778. }
  779. TEST_P(GLCopyTextureCHROMIUMTest, ImmutableTexture) {
  780. if (!GLTestHelper::HasExtension("GL_EXT_texture_storage")) {
  781. LOG(INFO) << "GL_EXT_texture_storage not supported. Skipping test...";
  782. return;
  783. }
  784. CopyType copy_type = GetParam();
  785. GLenum src_internal_formats[] = {GL_RGB8_OES, GL_RGBA8_OES, GL_BGRA8_EXT};
  786. GLenum dest_internal_formats[] = {GL_RGB8_OES, GL_RGBA8_OES, GL_BGRA8_EXT};
  787. uint8_t pixels[1 * 4] = {255u, 0u, 255u, 255u};
  788. for (auto src_internal_format : src_internal_formats) {
  789. for (auto dest_internal_format : dest_internal_formats) {
  790. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  791. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  792. glTexStorage2DEXT(GL_TEXTURE_2D, 1, src_internal_format, 1, 1);
  793. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1,
  794. ExtractFormatFrom(src_internal_format), GL_UNSIGNED_BYTE,
  795. pixels);
  796. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  797. glTexStorage2DEXT(GL_TEXTURE_2D, 1, dest_internal_format, 1, 1);
  798. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  799. GL_TEXTURE_2D, textures_[1], 0);
  800. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  801. if (copy_type == TexImage) {
  802. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  803. ExtractFormatFrom(dest_internal_format),
  804. GL_UNSIGNED_BYTE, false, false, false);
  805. EXPECT_TRUE(glGetError() == GL_INVALID_OPERATION);
  806. } else {
  807. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1],
  808. 0, 0, 0, 0, 0, 1, 1, false, false, false);
  809. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  810. // Check the FB is still bound.
  811. GLint value = 0;
  812. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
  813. GLuint fb_id = value;
  814. EXPECT_EQ(framebuffer_id_, fb_id);
  815. // Check that FB is complete.
  816. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  817. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  818. GLTestHelper::CheckPixels(0, 0, 1, 1, 0, pixels, nullptr);
  819. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  820. }
  821. glDeleteTextures(2, textures_);
  822. glDeleteFramebuffers(1, &framebuffer_id_);
  823. }
  824. }
  825. }
  826. TEST_P(GLCopyTextureCHROMIUMTest, InternalFormat) {
  827. CopyType copy_type = GetParam();
  828. constexpr GLint src_formats[] = {
  829. GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGRA_EXT};
  830. constexpr GLint dest_formats[] = {GL_RGB, GL_RGBA, GL_BGRA_EXT};
  831. for (const auto src_format : src_formats) {
  832. for (const auto dst_format : dest_formats) {
  833. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  834. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  835. glTexImage2D(GL_TEXTURE_2D, 0, src_format, 1, 1, 0, src_format,
  836. GL_UNSIGNED_BYTE, nullptr);
  837. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  838. if (copy_type == TexImage) {
  839. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  840. dst_format, GL_UNSIGNED_BYTE, false, false,
  841. false);
  842. } else {
  843. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  844. glTexImage2D(GL_TEXTURE_2D, 0, dst_format, 1, 1, 0, dst_format,
  845. GL_UNSIGNED_BYTE, nullptr);
  846. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  847. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1],
  848. 0, 0, 0, 0, 0, 1, 1, false, false, false);
  849. }
  850. EXPECT_TRUE(GL_NO_ERROR == glGetError())
  851. << "src_format: " << gl::GLEnums::GetStringEnum(src_format)
  852. << " dst_format: " << gl::GLEnums::GetStringEnum(dst_format);
  853. glDeleteTextures(2, textures_);
  854. glDeleteFramebuffers(1, &framebuffer_id_);
  855. }
  856. }
  857. }
  858. TEST_P(GLCopyTextureCHROMIUMTest, InternalFormatRGBFloat) {
  859. if (!GLTestHelper::HasExtension("GL_CHROMIUM_color_buffer_float_rgb")) {
  860. LOG(INFO)
  861. << "GL_CHROMIUM_color_buffer_float_rgb not supported. Skipping test...";
  862. return;
  863. }
  864. // TODO(qiankun.miao@intel.com): since RunCopyTexture requires dest texture to
  865. // be texture complete, skip this test if float texture is not color
  866. // filterable. We should remove this limitation when we find a way doesn't
  867. // require dest texture to be texture complete in RunCopyTexture.
  868. if (!gl_.decoder()
  869. ->GetFeatureInfo()
  870. ->feature_flags()
  871. .enable_texture_float_linear) {
  872. LOG(INFO) << "RGB32F texture is not filterable. Skipping test...";
  873. return;
  874. }
  875. CopyType copy_type = GetParam();
  876. FormatType src_format_type = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
  877. FormatType dest_format_type = {GL_RGB32F, GL_RGB, GL_FLOAT};
  878. RunCopyTexture(GL_TEXTURE_2D, copy_type, src_format_type, 0, dest_format_type,
  879. 0, false);
  880. }
  881. TEST_P(GLCopyTextureCHROMIUMTest, InternalFormatRGBAFloat) {
  882. if (!GLTestHelper::HasExtension("GL_CHROMIUM_color_buffer_float_rgba")) {
  883. LOG(INFO) << "GL_CHROMIUM_color_buffer_float_rgba not supported. Skipping "
  884. "test...";
  885. return;
  886. }
  887. // TODO(qiankun.miao@intel.com): since RunCopyTexture requires dest texture to
  888. // be texture complete, skip this test if float texture is not color
  889. // filterable. We should remove this limitation when we find a way doesn't
  890. // require dest texture to be texture complete in RunCopyTexture.
  891. if (!gl_.decoder()
  892. ->GetFeatureInfo()
  893. ->feature_flags()
  894. .enable_texture_float_linear) {
  895. LOG(INFO) << "RGBA32F texture is not filterable. Skipping test...";
  896. return;
  897. }
  898. CopyType copy_type = GetParam();
  899. FormatType src_format_type = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
  900. FormatType dest_format_type = {GL_RGBA32F, GL_RGBA, GL_FLOAT};
  901. RunCopyTexture(GL_TEXTURE_2D, copy_type, src_format_type, 0, dest_format_type,
  902. 0, false);
  903. }
  904. TEST_P(GLCopyTextureCHROMIUMTest, InternalFormatNotSupported) {
  905. CopyType copy_type = GetParam();
  906. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  907. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  908. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  909. nullptr);
  910. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  911. // Check unsupported format reports error.
  912. GLint unsupported_dest_formats[] = {GL_RED, GL_RG};
  913. for (size_t dest_index = 0; dest_index < std::size(unsupported_dest_formats);
  914. dest_index++) {
  915. if (copy_type == TexImage) {
  916. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  917. unsupported_dest_formats[dest_index],
  918. GL_UNSIGNED_BYTE, false, false, false);
  919. EXPECT_THAT(glGetError(),
  920. testing::AnyOf(GL_INVALID_VALUE, GL_INVALID_OPERATION))
  921. << "dest_index:" << dest_index;
  922. } else {
  923. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  924. glTexImage2D(GL_TEXTURE_2D, 0, unsupported_dest_formats[dest_index], 1, 1,
  925. 0, unsupported_dest_formats[dest_index], GL_UNSIGNED_BYTE,
  926. nullptr);
  927. // clear GL_INVALID_ENUM error from glTexImage2D on ES2 devices
  928. glGetError();
  929. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  930. 0, 0, 0, 0, 1, 1, false, false, false);
  931. EXPECT_TRUE(GL_INVALID_OPERATION == glGetError())
  932. << "dest_index:" << dest_index;
  933. }
  934. }
  935. glDeleteTextures(2, textures_);
  936. glDeleteFramebuffers(1, &framebuffer_id_);
  937. }
  938. TEST_F(GLCopyTextureCHROMIUMTest, InternalFormatTypeCombinationNotSupported) {
  939. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  940. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  941. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  942. nullptr);
  943. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  944. // Check unsupported internal_format/type combination reports error.
  945. struct FormatType { GLenum format, type; };
  946. FormatType unsupported_format_types[] = {
  947. {GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4},
  948. {GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1},
  949. {GL_RGBA, GL_UNSIGNED_SHORT_5_6_5},
  950. };
  951. for (size_t dest_index = 0; dest_index < std::size(unsupported_format_types);
  952. dest_index++) {
  953. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  954. unsupported_format_types[dest_index].format,
  955. unsupported_format_types[dest_index].type, false,
  956. false, false);
  957. EXPECT_TRUE(GL_INVALID_OPERATION == glGetError())
  958. << "dest_index:" << dest_index;
  959. }
  960. glDeleteTextures(2, textures_);
  961. glDeleteFramebuffers(1, &framebuffer_id_);
  962. }
  963. TEST_P(GLCopyTextureCHROMIUMTest, CopyTextureLevel) {
  964. CopyType copy_type = GetParam();
  965. // Copy from RGB source texture to dest texture.
  966. FormatType src_format_type = {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE};
  967. FormatType dest_format_types[] = {
  968. {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE},
  969. {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
  970. };
  971. // Source level must be 0 in ES2 context.
  972. GLint source_level = 0;
  973. for (GLint dest_level = 0; dest_level < 3; dest_level++) {
  974. for (auto dest_format_type : dest_format_types) {
  975. RunCopyTexture(GL_TEXTURE_2D, copy_type, src_format_type, source_level,
  976. dest_format_type, dest_level, false);
  977. }
  978. }
  979. }
  980. TEST_P(GLCopyTextureCHROMIUMES3Test, CopyTextureLevel) {
  981. if (ShouldSkipTest())
  982. return;
  983. if (gl_.gpu_preferences().use_passthrough_cmd_decoder) {
  984. // TODO(geofflang): anglebug.com/1932
  985. LOG(INFO)
  986. << "Passthrough command decoder expected failure. Skipping test...";
  987. return;
  988. }
  989. CopyType copy_type = GetParam();
  990. // Copy from RGBA source texture to dest texture.
  991. FormatType src_format_type = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
  992. FormatType dest_format_types[] = {
  993. {GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE},
  994. {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
  995. {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE},
  996. };
  997. for (GLint source_level = 0; source_level < 3; source_level++) {
  998. for (GLint dest_level = 0; dest_level < 3; dest_level++) {
  999. for (auto dest_format_type : dest_format_types) {
  1000. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
  1001. // TODO(qiankun.miao@intel.com): source_level > 0 or dest_level > 0
  1002. // isn't available due to renderinig bug for non-zero base level in
  1003. // NVIDIA Windows: crbug.com/679639 and Android: crbug.com/680460.
  1004. if (dest_level > 0)
  1005. continue;
  1006. #endif
  1007. RunCopyTexture(GL_TEXTURE_2D, copy_type, src_format_type, source_level,
  1008. dest_format_type, dest_level, true);
  1009. }
  1010. }
  1011. }
  1012. }
  1013. TEST_P(GLCopyTextureCHROMIUMTest, CopyTextureCubeMap) {
  1014. CopyType copy_type = GetParam();
  1015. GLenum dest_targets[] = {
  1016. GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
  1017. GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
  1018. GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
  1019. FormatType src_format_type = {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE};
  1020. FormatType dest_format_types[] = {
  1021. {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE}, {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
  1022. };
  1023. GLint source_level = 0;
  1024. GLint dest_level = 0;
  1025. for (auto dest_format_type : dest_format_types) {
  1026. for (auto dest_target : dest_targets) {
  1027. RunCopyTexture(dest_target, copy_type, src_format_type, source_level,
  1028. dest_format_type, dest_level, false);
  1029. }
  1030. }
  1031. }
  1032. TEST_P(GLCopyTextureCHROMIUMES3Test, CopyTextureCubeMap) {
  1033. if (ShouldSkipTest())
  1034. return;
  1035. CopyType copy_type = GetParam();
  1036. GLenum dest_targets[] = {
  1037. GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
  1038. GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
  1039. GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
  1040. FormatType src_format_type = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
  1041. FormatType dest_format_types[] = {
  1042. {GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE},
  1043. {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
  1044. {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE},
  1045. };
  1046. GLint source_level = 0;
  1047. GLint dest_level = 0;
  1048. for (auto dest_format_type : dest_format_types) {
  1049. for (auto dest_target : dest_targets) {
  1050. RunCopyTexture(dest_target, copy_type, src_format_type, source_level,
  1051. dest_format_type, dest_level, true);
  1052. }
  1053. }
  1054. }
  1055. // Test to ensure that the destination texture is redefined if the properties
  1056. // are different.
  1057. TEST_F(GLCopyTextureCHROMIUMTest, RedefineDestinationTexture) {
  1058. uint8_t pixels[4 * 4] = {255u, 0u, 0u, 255u, 255u, 0u, 0u, 255u,
  1059. 255u, 0u, 0u, 255u, 255u, 0u, 0u, 255u};
  1060. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1061. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1062. glTexImage2D(
  1063. GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  1064. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1065. glTexImage2D(GL_TEXTURE_2D,
  1066. 0,
  1067. GL_BGRA_EXT,
  1068. 1,
  1069. 1,
  1070. 0,
  1071. GL_BGRA_EXT,
  1072. GL_UNSIGNED_BYTE,
  1073. pixels);
  1074. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1075. // GL_INVALID_OPERATION due to "intrinsic format" != "internal format".
  1076. glTexSubImage2D(
  1077. GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  1078. EXPECT_TRUE(GL_INVALID_OPERATION == glGetError());
  1079. // GL_INVALID_VALUE due to bad dimensions.
  1080. glTexSubImage2D(
  1081. GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
  1082. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1083. // If the dest texture has different properties, glCopyTextureCHROMIUM()
  1084. // redefines them.
  1085. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1086. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1087. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1088. // glTexSubImage2D() succeeds because textures_[1] is redefined into 2x2
  1089. // dimension and GL_RGBA format.
  1090. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1091. glTexSubImage2D(
  1092. GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  1093. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1094. // Check the FB is still bound.
  1095. GLint value = 0;
  1096. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
  1097. GLuint fb_id = value;
  1098. EXPECT_EQ(framebuffer_id_, fb_id);
  1099. // Check that FB is complete.
  1100. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  1101. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  1102. GLTestHelper::CheckPixels(1, 1, 1, 1, 0, &pixels[12], nullptr);
  1103. glDeleteTextures(2, textures_);
  1104. glDeleteFramebuffers(1, &framebuffer_id_);
  1105. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1106. }
  1107. namespace {
  1108. void glEnableDisable(GLint param, GLboolean value) {
  1109. if (value)
  1110. glEnable(param);
  1111. else
  1112. glDisable(param);
  1113. }
  1114. } // unnamed namespace
  1115. // Validate that some basic GL state is not touched upon execution of
  1116. // the extension.
  1117. TEST_P(GLCopyTextureCHROMIUMTest, BasicStatePreservation) {
  1118. CopyType copy_type = GetParam();
  1119. uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u};
  1120. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1121. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1122. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1123. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1124. pixels);
  1125. if (copy_type == TexSubImage) {
  1126. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1127. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1128. nullptr);
  1129. }
  1130. GLboolean reference_settings[2] = { GL_TRUE, GL_FALSE };
  1131. for (int x = 0; x < 2; ++x) {
  1132. GLboolean setting = reference_settings[x];
  1133. glEnableDisable(GL_DEPTH_TEST, setting);
  1134. glEnableDisable(GL_SCISSOR_TEST, setting);
  1135. glEnableDisable(GL_STENCIL_TEST, setting);
  1136. glEnableDisable(GL_CULL_FACE, setting);
  1137. glEnableDisable(GL_BLEND, setting);
  1138. glColorMask(setting, setting, setting, setting);
  1139. glDepthMask(setting);
  1140. glActiveTexture(GL_TEXTURE1 + x);
  1141. if (copy_type == TexImage) {
  1142. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1143. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1144. } else {
  1145. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1146. 0, 0, 0, 0, 1, 1, false, false, false);
  1147. }
  1148. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1149. EXPECT_EQ(setting, glIsEnabled(GL_DEPTH_TEST));
  1150. EXPECT_EQ(setting, glIsEnabled(GL_SCISSOR_TEST));
  1151. EXPECT_EQ(setting, glIsEnabled(GL_STENCIL_TEST));
  1152. EXPECT_EQ(setting, glIsEnabled(GL_CULL_FACE));
  1153. EXPECT_EQ(setting, glIsEnabled(GL_BLEND));
  1154. GLboolean bool_array[4] = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE };
  1155. glGetBooleanv(GL_DEPTH_WRITEMASK, bool_array);
  1156. EXPECT_EQ(setting, bool_array[0]);
  1157. bool_array[0] = GL_FALSE;
  1158. glGetBooleanv(GL_COLOR_WRITEMASK, bool_array);
  1159. EXPECT_EQ(setting, bool_array[0]);
  1160. EXPECT_EQ(setting, bool_array[1]);
  1161. EXPECT_EQ(setting, bool_array[2]);
  1162. EXPECT_EQ(setting, bool_array[3]);
  1163. GLint active_texture = 0;
  1164. glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
  1165. EXPECT_EQ(GL_TEXTURE1 + x, active_texture);
  1166. }
  1167. glDeleteTextures(2, textures_);
  1168. glDeleteFramebuffers(1, &framebuffer_id_);
  1169. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1170. }
  1171. TEST_P(GLCopyTextureCHROMIUMES3Test, SamplerStatePreserved) {
  1172. if (ShouldSkipTest())
  1173. return;
  1174. CopyType copy_type = GetParam();
  1175. // Setup the texture used for the extension invocation.
  1176. uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u};
  1177. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1178. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1179. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1180. pixels);
  1181. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1182. if (copy_type == TexSubImage) {
  1183. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1184. nullptr);
  1185. }
  1186. GLuint sampler_id;
  1187. glGenSamplers(1, &sampler_id);
  1188. glBindSampler(0, sampler_id);
  1189. if (copy_type == TexImage) {
  1190. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1191. GL_RGBA, GL_UNSIGNED_BYTE, false, false, true);
  1192. } else {
  1193. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1194. 0, 0, 0, 1, 1, false, false, true);
  1195. }
  1196. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1197. GLint bound_sampler = 0;
  1198. glGetIntegerv(GL_SAMPLER_BINDING, &bound_sampler);
  1199. EXPECT_EQ(sampler_id, static_cast<GLuint>(bound_sampler));
  1200. glDeleteSamplers(1, &sampler_id);
  1201. }
  1202. // Verify that invocation of the extension does not modify the bound
  1203. // texture state.
  1204. TEST_P(GLCopyTextureCHROMIUMTest, TextureStatePreserved) {
  1205. CopyType copy_type = GetParam();
  1206. // Setup the texture used for the extension invocation.
  1207. uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u};
  1208. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1209. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1210. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1211. pixels);
  1212. if (copy_type == TexSubImage) {
  1213. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1214. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1215. nullptr);
  1216. }
  1217. GLuint texture_ids[2];
  1218. glGenTextures(2, texture_ids);
  1219. glActiveTexture(GL_TEXTURE0);
  1220. glBindTexture(GL_TEXTURE_2D, texture_ids[0]);
  1221. glActiveTexture(GL_TEXTURE1);
  1222. glBindTexture(GL_TEXTURE_2D, texture_ids[1]);
  1223. if (copy_type == TexImage) {
  1224. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1225. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1226. } else {
  1227. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1228. 0, 0, 0, 1, 1, false, false, false);
  1229. }
  1230. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1231. GLint active_texture = 0;
  1232. glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
  1233. EXPECT_EQ(GL_TEXTURE1, active_texture);
  1234. GLint bound_texture = 0;
  1235. glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
  1236. EXPECT_EQ(texture_ids[1], static_cast<GLuint>(bound_texture));
  1237. glBindTexture(GL_TEXTURE_2D, 0);
  1238. bound_texture = 0;
  1239. glActiveTexture(GL_TEXTURE0);
  1240. glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
  1241. EXPECT_EQ(texture_ids[0], static_cast<GLuint>(bound_texture));
  1242. glBindTexture(GL_TEXTURE_2D, 0);
  1243. glDeleteTextures(2, texture_ids);
  1244. glDeleteTextures(2, textures_);
  1245. glDeleteFramebuffers(1, &framebuffer_id_);
  1246. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1247. }
  1248. // Verify that invocation of the extension does not perturb the currently
  1249. // bound FBO state.
  1250. TEST_P(GLCopyTextureCHROMIUMTest, FBOStatePreserved) {
  1251. CopyType copy_type = GetParam();
  1252. // Setup the texture used for the extension invocation.
  1253. uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u};
  1254. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1255. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1256. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1257. pixels);
  1258. if (copy_type == TexSubImage) {
  1259. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1260. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1261. nullptr);
  1262. }
  1263. GLuint texture_id;
  1264. glGenTextures(1, &texture_id);
  1265. glBindTexture(GL_TEXTURE_2D, texture_id);
  1266. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1267. 0);
  1268. GLuint renderbuffer_id;
  1269. glGenRenderbuffers(1, &renderbuffer_id);
  1270. glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_id);
  1271. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 1, 1);
  1272. GLuint framebuffer_id;
  1273. glGenFramebuffers(1, &framebuffer_id);
  1274. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
  1275. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
  1276. texture_id, 0);
  1277. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  1278. GL_RENDERBUFFER, renderbuffer_id);
  1279. EXPECT_TRUE(
  1280. GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
  1281. // Test that we can write to the bound framebuffer
  1282. uint8_t expected_color[4] = {255u, 255u, 0, 255u};
  1283. glClearColor(1.0, 1.0, 0, 1.0);
  1284. glClear(GL_COLOR_BUFFER_BIT);
  1285. GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_color, nullptr);
  1286. if (copy_type == TexImage) {
  1287. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1288. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1289. } else {
  1290. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1291. 0, 0, 0, 1, 1, false, false, false);
  1292. }
  1293. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1294. EXPECT_TRUE(glIsFramebuffer(framebuffer_id));
  1295. // Ensure that reading from the framebuffer produces correct pixels.
  1296. GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_color, nullptr);
  1297. uint8_t expected_color2[4] = {255u, 0, 255u, 255u};
  1298. glClearColor(1.0, 0, 1.0, 1.0);
  1299. glClear(GL_COLOR_BUFFER_BIT);
  1300. GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_color2, nullptr);
  1301. GLint bound_fbo = 0;
  1302. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_fbo);
  1303. EXPECT_EQ(framebuffer_id, static_cast<GLuint>(bound_fbo));
  1304. GLint fbo_params = 0;
  1305. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  1306. GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
  1307. &fbo_params);
  1308. EXPECT_EQ(GL_TEXTURE, fbo_params);
  1309. fbo_params = 0;
  1310. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  1311. GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
  1312. &fbo_params);
  1313. EXPECT_EQ(texture_id, static_cast<GLuint>(fbo_params));
  1314. fbo_params = 0;
  1315. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  1316. GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
  1317. &fbo_params);
  1318. EXPECT_EQ(GL_RENDERBUFFER, fbo_params);
  1319. fbo_params = 0;
  1320. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
  1321. GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
  1322. &fbo_params);
  1323. EXPECT_EQ(renderbuffer_id, static_cast<GLuint>(fbo_params));
  1324. glDeleteRenderbuffers(1, &renderbuffer_id);
  1325. glDeleteTextures(1, &texture_id);
  1326. glDeleteFramebuffers(1, &framebuffer_id);
  1327. glDeleteTextures(2, textures_);
  1328. glDeleteFramebuffers(1, &framebuffer_id_);
  1329. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1330. }
  1331. TEST_P(GLCopyTextureCHROMIUMTest, ProgramStatePreservation) {
  1332. CopyType copy_type = GetParam();
  1333. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1334. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1335. glBindTexture(GL_TEXTURE_2D, 0);
  1336. GLManager gl2;
  1337. GLManager::Options options;
  1338. options.size = gfx::Size(16, 16);
  1339. options.share_group_manager = &gl_;
  1340. gl2.Initialize(options);
  1341. gl_.MakeCurrent();
  1342. static const char* v_shader_str =
  1343. "attribute vec4 g_Position;\n"
  1344. "void main()\n"
  1345. "{\n"
  1346. " gl_Position = g_Position;\n"
  1347. "}\n";
  1348. static const char* f_shader_str =
  1349. "precision mediump float;\n"
  1350. "void main()\n"
  1351. "{\n"
  1352. " gl_FragColor = vec4(0,1,0,1);\n"
  1353. "}\n";
  1354. GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
  1355. glUseProgram(program);
  1356. GLuint position_loc = glGetAttribLocation(program, "g_Position");
  1357. glFlush();
  1358. // Delete program from other context.
  1359. gl2.MakeCurrent();
  1360. glDeleteProgram(program);
  1361. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1362. glFlush();
  1363. // Program should still be usable on this context.
  1364. gl_.MakeCurrent();
  1365. GLTestHelper::SetupUnitQuad(position_loc);
  1366. // test using program before
  1367. uint8_t expected[] = {
  1368. 0, 255, 0, 255,
  1369. };
  1370. uint8_t zero[] = {
  1371. 0, 0, 0, 0,
  1372. };
  1373. glClear(GL_COLOR_BUFFER_BIT);
  1374. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, zero, nullptr));
  1375. glDrawArrays(GL_TRIANGLES, 0, 6);
  1376. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected, nullptr));
  1377. // Call copyTextureCHROMIUM
  1378. uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u};
  1379. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1380. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1381. pixels);
  1382. if (copy_type == TexImage) {
  1383. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1384. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1385. } else {
  1386. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1387. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1388. nullptr);
  1389. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1390. 0, 0, 0, 1, 1, false, false, false);
  1391. }
  1392. // test using program after
  1393. glClear(GL_COLOR_BUFFER_BIT);
  1394. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, zero, nullptr));
  1395. glDrawArrays(GL_TRIANGLES, 0, 6);
  1396. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected, nullptr));
  1397. glDeleteTextures(2, textures_);
  1398. glDeleteFramebuffers(1, &framebuffer_id_);
  1399. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1400. gl2.MakeCurrent();
  1401. gl2.Destroy();
  1402. gl_.MakeCurrent();
  1403. }
  1404. // Test that glCopyTextureCHROMIUM doesn't leak uninitialized textures.
  1405. TEST_P(GLCopyTextureCHROMIUMTest, UninitializedSource) {
  1406. CopyType copy_type = GetParam();
  1407. const GLsizei kWidth = 64, kHeight = 64;
  1408. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1409. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1410. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
  1411. GL_UNSIGNED_BYTE, nullptr);
  1412. if (copy_type == TexImage) {
  1413. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1414. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1415. } else {
  1416. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1417. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
  1418. GL_UNSIGNED_BYTE, nullptr);
  1419. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1420. 0, 0, 0, kWidth, kHeight, false, false, false);
  1421. }
  1422. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1423. uint8_t pixels[kHeight][kWidth][4] = {{{1}}};
  1424. glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  1425. for (int x = 0; x < kWidth; ++x) {
  1426. for (int y = 0; y < kHeight; ++y) {
  1427. EXPECT_EQ(0, pixels[y][x][0]);
  1428. EXPECT_EQ(0, pixels[y][x][1]);
  1429. EXPECT_EQ(0, pixels[y][x][2]);
  1430. EXPECT_EQ(0, pixels[y][x][3]);
  1431. }
  1432. }
  1433. glDeleteTextures(2, textures_);
  1434. glDeleteFramebuffers(1, &framebuffer_id_);
  1435. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1436. }
  1437. TEST_F(GLCopyTextureCHROMIUMTest, CopySubTextureDimension) {
  1438. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1439. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1440. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1441. nullptr);
  1442. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1443. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1444. nullptr);
  1445. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 1,
  1446. 1, 0, 0, 1, 1, false, false, false);
  1447. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1448. // xoffset < 0
  1449. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, -1,
  1450. 1, 0, 0, 1, 1, false, false, false);
  1451. EXPECT_TRUE(glGetError() == GL_INVALID_VALUE);
  1452. // x < 0
  1453. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 1,
  1454. 1, -1, 0, 1, 1, false, false, false);
  1455. EXPECT_TRUE(glGetError() == GL_INVALID_VALUE);
  1456. // xoffset + width > dest_width
  1457. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 2,
  1458. 2, 0, 0, 2, 2, false, false, false);
  1459. EXPECT_TRUE(glGetError() == GL_INVALID_VALUE);
  1460. // x + width > source_width
  1461. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1462. 0, 1, 1, 2, 2, false, false, false);
  1463. EXPECT_TRUE(glGetError() == GL_INVALID_VALUE);
  1464. glDeleteTextures(2, textures_);
  1465. glDeleteFramebuffers(1, &framebuffer_id_);
  1466. }
  1467. TEST_F(GLCopyTextureCHROMIUMTest, CopyTextureInvalidTextureIds) {
  1468. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1469. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1470. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1471. nullptr);
  1472. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1473. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1474. nullptr);
  1475. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, 99993, 0, GL_RGBA,
  1476. GL_UNSIGNED_BYTE, false, false, false);
  1477. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1478. glCopyTextureCHROMIUM(99994, 0, GL_TEXTURE_2D, textures_[1], 0, GL_RGBA,
  1479. GL_UNSIGNED_BYTE, false, false, false);
  1480. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1481. glCopyTextureCHROMIUM(99995, 0, GL_TEXTURE_2D, 99996, 0, GL_RGBA,
  1482. GL_UNSIGNED_BYTE, false, false, false);
  1483. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1484. glCopyTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0,
  1485. GL_RGBA, GL_UNSIGNED_BYTE, false, false, false);
  1486. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1487. glDeleteTextures(2, textures_);
  1488. glDeleteFramebuffers(1, &framebuffer_id_);
  1489. }
  1490. TEST_F(GLCopyTextureCHROMIUMTest, CopySubTextureInvalidTextureIds) {
  1491. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1492. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1493. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1494. nullptr);
  1495. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1496. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1497. nullptr);
  1498. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, 99993, 0, 1, 1, 0, 0,
  1499. 1, 1, false, false, false);
  1500. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1501. glCopySubTextureCHROMIUM(99994, 0, GL_TEXTURE_2D, textures_[1], 0, 1, 1, 0, 0,
  1502. 1, 1, false, false, false);
  1503. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1504. glCopySubTextureCHROMIUM(99995, 0, GL_TEXTURE_2D, 99996, 0, 1, 1, 0, 0, 1, 1,
  1505. false, false, false);
  1506. EXPECT_TRUE(GL_INVALID_VALUE == glGetError());
  1507. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 1,
  1508. 1, 0, 0, 1, 1, false, false, false);
  1509. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1510. glDeleteTextures(2, textures_);
  1511. glDeleteFramebuffers(1, &framebuffer_id_);
  1512. }
  1513. TEST_F(GLCopyTextureCHROMIUMTest, CopySubTextureOffset) {
  1514. uint8_t rgba_pixels[4 * 4] = {255u, 0u, 0u, 255u, 0u, 255u, 0u, 255u,
  1515. 0u, 0u, 255u, 255u, 0u, 0u, 0u, 255u};
  1516. CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D);
  1517. glBindTexture(GL_TEXTURE_2D, textures_[0]);
  1518. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1519. rgba_pixels);
  1520. uint8_t transparent_pixels[4 * 4] = {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
  1521. 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u};
  1522. glBindTexture(GL_TEXTURE_2D, textures_[1]);
  1523. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
  1524. transparent_pixels);
  1525. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 1,
  1526. 1, 0, 0, 1, 1, false, false, false);
  1527. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  1528. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 1,
  1529. 0, 1, 0, 1, 1, false, false, false);
  1530. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  1531. glCopySubTextureCHROMIUM(textures_[0], 0, GL_TEXTURE_2D, textures_[1], 0, 0,
  1532. 1, 0, 1, 1, 1, false, false, false);
  1533. EXPECT_TRUE(glGetError() == GL_NO_ERROR);
  1534. // Check the FB is still bound.
  1535. GLint value = 0;
  1536. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value);
  1537. GLuint fb_id = value;
  1538. EXPECT_EQ(framebuffer_id_, fb_id);
  1539. // Check that FB is complete.
  1540. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  1541. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  1542. uint8_t transparent[1 * 4] = {0u, 0u, 0u, 0u};
  1543. uint8_t red[1 * 4] = {255u, 0u, 0u, 255u};
  1544. uint8_t green[1 * 4] = {0u, 255u, 0u, 255u};
  1545. uint8_t blue[1 * 4] = {0u, 0u, 255u, 255u};
  1546. GLTestHelper::CheckPixels(0, 0, 1, 1, 0, transparent, nullptr);
  1547. GLTestHelper::CheckPixels(1, 1, 1, 1, 0, red, nullptr);
  1548. GLTestHelper::CheckPixels(1, 0, 1, 1, 0, green, nullptr);
  1549. GLTestHelper::CheckPixels(0, 1, 1, 1, 0, blue, nullptr);
  1550. EXPECT_TRUE(GL_NO_ERROR == glGetError());
  1551. glDeleteTextures(2, textures_);
  1552. glDeleteFramebuffers(1, &framebuffer_id_);
  1553. }
  1554. } // namespace gpu