1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program EGL Module 3 * --------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief EGL image tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "teglImageTests.hpp" 25 26 #include "teglImageFormatTests.hpp" 27 28 #include "egluNativeDisplay.hpp" 29 #include "egluNativeWindow.hpp" 30 #include "egluNativePixmap.hpp" 31 #include "egluStrUtil.hpp" 32 #include "egluUtil.hpp" 33 34 #include "gluDefs.hpp" 35 #include "gluStrUtil.hpp" 36 37 #include "tcuTestLog.hpp" 38 #include "tcuCommandLine.hpp" 39 40 41 #include <algorithm> 42 #include <sstream> 43 #include <string> 44 #include <vector> 45 #include <set> 46 47 #include <EGL/eglext.h> 48 49 #include <GLES2/gl2.h> 50 #include <GLES2/gl2ext.h> 51 52 using tcu::TestLog; 53 54 using std::string; 55 using std::vector; 56 using std::set; 57 58 namespace deqp 59 { 60 namespace egl 61 { 62 63 namespace Image 64 { 65 66 bool checkExtensions (const tcu::egl::Display& dpy, const char** first, const char** last, vector<const char*>& unsupported) 67 { 68 vector<string> extensions; 69 dpy.getExtensions(extensions); 70 71 set<string> extSet(extensions.begin(), extensions.end()); 72 73 unsupported.clear(); 74 75 for (const char** extIter = first; extIter != last; extIter++) 76 { 77 const char* ext = *extIter; 78 79 if (extSet.find(ext) == extSet.end()) 80 unsupported.push_back(ext); 81 } 82 83 return unsupported.size() == 0; 84 } 85 86 string join (const vector<const char*>& parts, const char* separator) 87 { 88 std::ostringstream str; 89 for (std::vector<const char*>::const_iterator i = parts.begin(); i != parts.end(); i++) 90 { 91 if (i != parts.begin()) 92 str << separator; 93 str << *i; 94 } 95 return str.str(); 96 } 97 98 void checkExtensions (const tcu::egl::Display& dpy, const char** first, const char** last) 99 { 100 vector<const char*> unsupported; 101 if (!checkExtensions(dpy, first, last, unsupported)) 102 throw tcu::NotSupportedError("Extension not supported", join(unsupported, " ").c_str(), __FILE__, __LINE__); 103 } 104 105 template <size_t N> 106 void checkExtensions (const tcu::egl::Display& dpy, const char* (&extensions)[N]) 107 { 108 checkExtensions(dpy, &extensions[0], &extensions[N]); 109 } 110 111 #define CHECK_EXTENSIONS(EXTENSIONS) do { static const char* ext[] = EXTENSIONS; checkExtensions(m_eglTestCtx.getDisplay(), ext); } while (deGetFalse()) 112 113 template <typename RetVal> 114 RetVal checkCallError (tcu::TestContext& testCtx, const char* call, RetVal returnValue, EGLint expectError) 115 { 116 TestLog& log = testCtx.getLog(); 117 log << TestLog::Message << call << TestLog::EndMessage; 118 119 EGLint error = eglGetError(); 120 121 if (error != expectError) 122 { 123 log << TestLog::Message << " Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage; 124 log << TestLog::Message << " " << returnValue << " was returned" << TestLog::EndMessage; 125 126 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) 127 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code"); 128 } 129 130 return returnValue; 131 } 132 133 template <typename RetVal> 134 void checkCallReturn (tcu::TestContext& testCtx, const char* call, RetVal returnValue, RetVal expectReturnValue, EGLint expectError) 135 { 136 TestLog& log = testCtx.getLog(); 137 log << TestLog::Message << call << TestLog::EndMessage; 138 139 EGLint error = eglGetError(); 140 141 if (returnValue != expectReturnValue) 142 { 143 log << TestLog::Message << " Fail: Return value mismatch! Expected " << expectReturnValue << ", got " << returnValue << TestLog::EndMessage; 144 145 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) 146 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value"); 147 } 148 149 if (error != expectError) 150 { 151 log << TestLog::Message << " Fail: Error code mismatch! Expected " << eglu::getErrorStr(expectError) << ", got " << eglu::getErrorStr(error) << TestLog::EndMessage; 152 153 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) 154 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code"); 155 } 156 } 157 158 void checkGLCall (tcu::TestContext& testCtx, const char* call, GLenum expectError) 159 { 160 TestLog& log = testCtx.getLog(); 161 log << TestLog::Message << call << TestLog::EndMessage; 162 163 GLenum error = glGetError(); 164 165 if (error != expectError) 166 { 167 log << TestLog::Message << " Fail: Error code mismatch! Expected " << glu::getErrorStr(expectError) << ", got " << glu::getErrorStr(error) << TestLog::EndMessage; 168 169 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) 170 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error code"); 171 } 172 } 173 174 // \note These macros expect "TestContext m_testCtx" and "ExtFuncTable efTable" variables to be defined. 175 #define CHECK_EXT_CALL_RET(CALL, EXPECT_RETURN_VALUE, EXPECT_ERROR) checkCallReturn(m_testCtx, #CALL, efTable.CALL, (EXPECT_RETURN_VALUE), (EXPECT_ERROR)) 176 #define CHECK_EXT_CALL_ERR(CALL, EXPECT_ERROR) checkCallError(m_testCtx, #CALL, efTable.CALL, (EXPECT_ERROR)) 177 #define CHECK_GL_EXT_CALL(CALL, EXPECT_ERROR) do { efTable.CALL; checkGLCall(m_testCtx, #CALL, (EXPECT_ERROR)); } while (deGetFalse()) 178 179 class ExtFuncTable 180 { 181 public: 182 PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; 183 PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; 184 185 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; 186 PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES; 187 188 ExtFuncTable (void) 189 { 190 // EGL_KHR_image_base 191 eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); 192 eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR"); 193 194 // OES_EGL_image 195 glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); 196 glEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES"); 197 } 198 }; 199 200 class InvalidCreateImage : public TestCase 201 { 202 public: 203 InvalidCreateImage (EglTestContext& eglTestCtx) 204 : TestCase(eglTestCtx, "invalid_create_image", "eglCreateImageKHR() with invalid arguments") 205 { 206 } 207 208 IterateResult iterate (void) 209 { 210 EGLDisplay dpy = m_eglTestCtx.getDisplay().getEGLDisplay(); 211 TestLog& log = m_testCtx.getLog(); 212 ExtFuncTable efTable; 213 214 CHECK_EXTENSIONS({ "EGL_KHR_image_base" }); 215 216 // Initialize result to pass. 217 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 218 219 log << TestLog::Message << "Testing bad display (-1)..." << TestLog::EndMessage; 220 CHECK_EXT_CALL_RET(eglCreateImageKHR((EGLDisplay)-1, EGL_NO_CONTEXT, EGL_NONE, 0, DE_NULL), 221 EGL_NO_IMAGE_KHR, EGL_BAD_DISPLAY); 222 223 log << TestLog::Message << "Testing bad context (-1)..." << TestLog::EndMessage; 224 CHECK_EXT_CALL_RET(eglCreateImageKHR(dpy, (EGLContext)-1, EGL_NONE, 0, DE_NULL), 225 EGL_NO_IMAGE_KHR, EGL_BAD_CONTEXT); 226 227 log << TestLog::Message << "Testing bad parameter (-1).." << TestLog::EndMessage; 228 CHECK_EXT_CALL_RET(eglCreateImageKHR(dpy, EGL_NO_CONTEXT, (EGLenum)-1, 0, DE_NULL), 229 EGL_NO_IMAGE_KHR, EGL_BAD_PARAMETER); 230 231 return STOP; 232 } 233 }; 234 235 class GLES2Context 236 { 237 public: 238 GLES2Context (EglTestContext& eglTestCtx, EGLint configId, int width, int height) 239 : m_eglTestCtx (eglTestCtx) 240 , m_config (getConfigById(eglTestCtx.getDisplay(), configId)) 241 , m_context (eglTestCtx.getDisplay(), m_config, m_ctxAttrs, EGL_OPENGL_ES_API) 242 , m_window (DE_NULL) 243 , m_pixmap (DE_NULL) 244 , m_surface (DE_NULL) 245 { 246 tcu::egl::Display& dpy = eglTestCtx.getDisplay(); 247 EGLint surfaceTypeBits = dpy.getConfigAttrib(m_config, EGL_SURFACE_TYPE); 248 249 if (surfaceTypeBits & EGL_PBUFFER_BIT) 250 { 251 EGLint pbufferAttrs[] = 252 { 253 EGL_WIDTH, width, 254 EGL_HEIGHT, height, 255 EGL_NONE 256 }; 257 258 m_surface = new tcu::egl::PbufferSurface(dpy, m_config, pbufferAttrs); 259 } 260 else if (surfaceTypeBits & EGL_WINDOW_BIT) 261 { 262 m_window = eglTestCtx.createNativeWindow(dpy.getEGLDisplay(), m_config, DE_NULL, width, height, eglu::parseWindowVisibility(eglTestCtx.getTestContext().getCommandLine())); 263 m_surface = new tcu::egl::WindowSurface(dpy, eglu::createWindowSurface(eglTestCtx.getNativeDisplay(), *m_window, dpy.getEGLDisplay(), m_config, DE_NULL)); 264 } 265 else if (surfaceTypeBits & EGL_PIXMAP_BIT) 266 { 267 m_pixmap = eglTestCtx.createNativePixmap(dpy.getEGLDisplay(), m_config, DE_NULL, width, height); 268 m_surface = new tcu::egl::PixmapSurface(dpy, eglu::createPixmapSurface(eglTestCtx.getNativeDisplay(), *m_pixmap, dpy.getEGLDisplay(), m_config, DE_NULL)); 269 } 270 else 271 TCU_FAIL("No valid surface types supported in config"); 272 273 m_context.makeCurrent(*m_surface, *m_surface); 274 } 275 276 ~GLES2Context (void) 277 { 278 eglMakeCurrent(m_eglTestCtx.getDisplay().getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 279 280 delete m_window; 281 delete m_pixmap; 282 delete m_surface; 283 } 284 285 EGLDisplay getEglDisplay (void) 286 { 287 return m_eglTestCtx.getDisplay().getEGLDisplay(); 288 } 289 290 EGLContext getEglContext (void) 291 { 292 return m_context.getEGLContext(); 293 } 294 295 // Helper for selecting config. 296 static EGLint getConfigIdForApi (const vector<eglu::ConfigInfo>& configInfos, EGLint apiBits) 297 { 298 EGLint windowCfg = 0; 299 EGLint pixmapCfg = 0; 300 EGLint pbufferCfg = 0; 301 302 for (vector<eglu::ConfigInfo>::const_iterator cfgIter = configInfos.begin(); cfgIter != configInfos.end(); cfgIter++) 303 { 304 if ((cfgIter->renderableType & apiBits) == 0) 305 continue; 306 307 if (windowCfg == 0 && (cfgIter->surfaceType & EGL_WINDOW_BIT) != 0) 308 windowCfg = cfgIter->configId; 309 310 if (pixmapCfg == 0 && (cfgIter->surfaceType & EGL_PIXMAP_BIT) != 0) 311 pixmapCfg = cfgIter->configId; 312 313 if (pbufferCfg == 0 && (cfgIter->surfaceType & EGL_PBUFFER_BIT) != 0) 314 pbufferCfg = cfgIter->configId; 315 316 if (windowCfg && pixmapCfg && pbufferCfg) 317 break; 318 } 319 320 // Prefer configs in order: pbuffer, window, pixmap 321 if (pbufferCfg) 322 return pbufferCfg; 323 else if (windowCfg) 324 return windowCfg; 325 else if (pixmapCfg) 326 return pixmapCfg; 327 else 328 throw tcu::NotSupportedError("No compatible EGL configs found", "", __FILE__, __LINE__); 329 } 330 331 private: 332 static EGLConfig getConfigById (const tcu::egl::Display& dpy, EGLint configId) 333 { 334 EGLint attributes[] = { EGL_CONFIG_ID, configId, EGL_NONE }; 335 vector<EGLConfig> configs; 336 dpy.chooseConfig(attributes, configs); 337 TCU_CHECK(configs.size() == 1); 338 return configs[0]; 339 } 340 341 static const EGLint m_ctxAttrs[]; 342 343 EglTestContext& m_eglTestCtx; 344 EGLConfig m_config; 345 tcu::egl::Context m_context; 346 eglu::NativeWindow* m_window; 347 eglu::NativePixmap* m_pixmap; 348 tcu::egl::Surface* m_surface; 349 350 GLES2Context (const GLES2Context&); 351 GLES2Context& operator= (const GLES2Context&); 352 }; 353 354 const EGLint GLES2Context::m_ctxAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 355 356 class CreateImageGLES2 : public TestCase 357 { 358 public: 359 static const char* getTargetName (EGLint target) 360 { 361 switch (target) 362 { 363 case EGL_GL_TEXTURE_2D_KHR: return "tex2d"; 364 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: return "cubemap_pos_x"; 365 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: return "cubemap_neg_x"; 366 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: return "cubemap_pos_y"; 367 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: return "cubemap_neg_y"; 368 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: return "cubemap_pos_z"; 369 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: return "cubemap_neg_z"; 370 case EGL_GL_RENDERBUFFER_KHR: return "renderbuffer"; 371 default: DE_ASSERT(DE_FALSE); return ""; 372 } 373 } 374 375 static const char* getStorageName (GLenum storage) 376 { 377 switch (storage) 378 { 379 case GL_RGB: return "rgb"; 380 case GL_RGBA: return "rgba"; 381 case GL_DEPTH_COMPONENT16: return "depth_component_16"; 382 case GL_RGBA4: return "rgba4"; 383 case GL_RGB5_A1: return "rgb5_a1"; 384 case GL_RGB565: return "rgb565"; 385 case GL_STENCIL_INDEX8: return "stencil_index8"; 386 default: 387 DE_ASSERT(DE_FALSE); 388 return ""; 389 } 390 } 391 392 CreateImageGLES2 (EglTestContext& eglTestCtx, EGLint target, GLenum storage, bool useTexLevel0 = false) 393 : TestCase (eglTestCtx, (string("create_image_gles2_") + getTargetName(target) + "_" + getStorageName(storage) + (useTexLevel0 ? "_level0_only" : "")).c_str(), "Create EGLImage from GLES2 object") 394 , m_target (target) 395 , m_storage (storage) 396 , m_useTexLevel0 (useTexLevel0) 397 { 398 } 399 400 IterateResult iterate (void) 401 { 402 TestLog& log = m_testCtx.getLog(); 403 ExtFuncTable efTable; 404 405 if (m_target == EGL_GL_TEXTURE_2D_KHR) 406 CHECK_EXTENSIONS({"EGL_KHR_gl_texture_2D_image"}); 407 else if (m_target == EGL_GL_RENDERBUFFER_KHR) 408 CHECK_EXTENSIONS({"EGL_KHR_gl_renderbuffer_image"}); 409 else 410 CHECK_EXTENSIONS({"EGL_KHR_gl_texture_cubemap_image"}); 411 412 // Initialize result. 413 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 414 415 // Create GLES2 context 416 EGLint configId = GLES2Context::getConfigIdForApi(m_eglTestCtx.getConfigs(), EGL_OPENGL_ES2_BIT); 417 log << TestLog::Message << "Using EGL config " << configId << TestLog::EndMessage; 418 419 GLES2Context context(m_eglTestCtx, configId, 64, 64); 420 421 switch (m_target) 422 { 423 case EGL_GL_TEXTURE_2D_KHR: 424 { 425 deUint32 tex = 1; 426 GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, tex)); 427 428 // Specify mipmap level 0 429 GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, m_storage, 64, 64, 0, m_storage, GL_UNSIGNED_BYTE, DE_NULL)); 430 431 if (!m_useTexLevel0) 432 { 433 // Set minification filter to linear. This makes the texture complete. 434 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 435 } 436 // Else spec allows using incomplete texture when miplevel 0 is only used and specified. 437 438 // Create EGL image 439 EGLint attribs[] = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; 440 EGLImageKHR image = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)tex, attribs), EGL_SUCCESS); 441 if (image == EGL_NO_IMAGE_KHR) 442 { 443 log << TestLog::Message << " Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage; 444 445 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 446 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR"); 447 } 448 449 // Destroy image 450 CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS); 451 452 // Destroy texture object 453 GLU_CHECK_CALL(glDeleteTextures(1, &tex)); 454 455 break; 456 } 457 458 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 459 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 460 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 461 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 462 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 463 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 464 { 465 deUint32 tex = 1; 466 GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_CUBE_MAP, tex)); 467 468 // Specify mipmap level 0 for all faces 469 GLenum faces[] = 470 { 471 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 472 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 473 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 474 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 475 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 476 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 477 }; 478 for (int faceNdx = 0; faceNdx < DE_LENGTH_OF_ARRAY(faces); faceNdx++) 479 GLU_CHECK_CALL(glTexImage2D(faces[faceNdx], 0, m_storage, 64, 64, 0, m_storage, GL_UNSIGNED_BYTE, DE_NULL)); 480 481 if (!m_useTexLevel0) 482 { 483 // Set minification filter to linear. 484 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 485 } 486 487 // Create EGL image 488 EGLint attribs[] = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; 489 EGLImageKHR image = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), m_target, (EGLClientBuffer)(deUintptr)tex, attribs), EGL_SUCCESS); 490 if (image == EGL_NO_IMAGE_KHR) 491 { 492 log << TestLog::Message << " Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage; 493 494 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 495 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR"); 496 } 497 498 // Destroy image 499 CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS); 500 501 // Destroy texture object 502 GLU_CHECK_CALL(glDeleteTextures(1, &tex)); 503 504 break; 505 } 506 507 case EGL_GL_RENDERBUFFER_KHR: 508 { 509 // Create renderbuffer. 510 deUint32 rbo = 1; 511 GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, rbo)); 512 513 // Specify storage. 514 GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, m_storage, 64, 64)); 515 516 // Create EGL image 517 EGLImageKHR image = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_RENDERBUFFER_KHR, (EGLClientBuffer)(deUintptr)rbo, DE_NULL), EGL_SUCCESS); 518 if (image == EGL_NO_IMAGE_KHR) 519 { 520 log << TestLog::Message << " Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage; 521 522 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 523 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR"); 524 } 525 526 // Destroy image 527 CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS); 528 529 // Destroy texture object 530 GLU_CHECK_CALL(glDeleteRenderbuffers(1, &rbo)); 531 532 break; 533 } 534 535 default: 536 DE_ASSERT(DE_FALSE); 537 break; 538 } 539 540 return STOP; 541 } 542 543 private: 544 EGLint m_target; 545 GLenum m_storage; 546 bool m_useTexLevel0; 547 }; 548 549 class ImageTargetGLES2 : public TestCase 550 { 551 public: 552 static const char* getTargetName (GLenum target) 553 { 554 switch (target) 555 { 556 case GL_TEXTURE_2D: return "tex2d"; 557 case GL_RENDERBUFFER: return "renderbuffer"; 558 default: 559 DE_ASSERT(DE_FALSE); 560 return ""; 561 } 562 } 563 564 ImageTargetGLES2 (EglTestContext& eglTestCtx, GLenum target) 565 : TestCase (eglTestCtx, (string("image_target_gles2_") + getTargetName(target)).c_str(), "Use EGLImage as GLES2 object") 566 , m_target (target) 567 { 568 } 569 570 IterateResult iterate (void) 571 { 572 TestLog& log = m_testCtx.getLog(); 573 ExtFuncTable efTable; 574 575 // \todo [2011-07-21 pyry] Try all possible EGLImage sources 576 CHECK_EXTENSIONS({"EGL_KHR_gl_texture_2D_image"}); 577 578 // Initialize result. 579 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 580 581 // Create GLES2 context 582 EGLint configId = GLES2Context::getConfigIdForApi(m_eglTestCtx.getConfigs(), EGL_OPENGL_ES2_BIT); 583 log << TestLog::Message << "Using EGL config " << configId << TestLog::EndMessage; 584 585 GLES2Context context(m_eglTestCtx, configId, 64, 64); 586 587 // Check for OES_EGL_image 588 { 589 const char* glExt = (const char*)glGetString(GL_EXTENSIONS); 590 591 if (string(glExt).find("GL_OES_EGL_image") == string::npos) 592 throw tcu::NotSupportedError("Extension not supported", "GL_OES_EGL_image", __FILE__, __LINE__); 593 594 TCU_CHECK(efTable.glEGLImageTargetTexture2DOES); 595 TCU_CHECK(efTable.glEGLImageTargetRenderbufferStorageOES); 596 } 597 598 // Create GL_TEXTURE_2D and EGLImage from it. 599 log << TestLog::Message << "Creating EGLImage using GL_TEXTURE_2D with GL_RGBA storage" << TestLog::EndMessage; 600 601 deUint32 srcTex = 1; 602 GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, srcTex)); 603 GLU_CHECK_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL)); 604 GLU_CHECK_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 605 606 // Create EGL image 607 EGLint attribs[] = { EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE }; 608 EGLImageKHR image = CHECK_EXT_CALL_ERR(eglCreateImageKHR(context.getEglDisplay(), context.getEglContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)srcTex, attribs), EGL_SUCCESS); 609 if (image == EGL_NO_IMAGE_KHR) 610 { 611 log << TestLog::Message << " Fail: Got EGL_NO_IMAGE_KHR!" << TestLog::EndMessage; 612 613 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 614 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got EGL_NO_IMAGE_KHR"); 615 } 616 617 // Create texture or renderbuffer 618 if (m_target == GL_TEXTURE_2D) 619 { 620 log << TestLog::Message << "Creating GL_TEXTURE_2D from EGLimage" << TestLog::EndMessage; 621 622 deUint32 dstTex = 2; 623 GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, dstTex)); 624 CHECK_GL_EXT_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image), GL_NO_ERROR); 625 GLU_CHECK_CALL(glDeleteTextures(1, &dstTex)); 626 } 627 else 628 { 629 DE_ASSERT(m_target == GL_RENDERBUFFER); 630 631 log << TestLog::Message << "Creating GL_RENDERBUFFER from EGLimage" << TestLog::EndMessage; 632 633 deUint32 dstRbo = 2; 634 GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, dstRbo)); 635 CHECK_GL_EXT_CALL(glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)image), GL_NO_ERROR); 636 GLU_CHECK_CALL(glDeleteRenderbuffers(1, &dstRbo)); 637 } 638 639 // Destroy image 640 CHECK_EXT_CALL_RET(eglDestroyImageKHR(context.getEglDisplay(), image), (EGLBoolean)EGL_TRUE, EGL_SUCCESS); 641 642 // Destroy source texture object 643 GLU_CHECK_CALL(glDeleteTextures(1, &srcTex)); 644 645 return STOP; 646 } 647 648 private: 649 GLenum m_target; 650 }; 651 652 class ApiTests : public TestCaseGroup 653 { 654 public: 655 ApiTests (EglTestContext& eglTestCtx) 656 : TestCaseGroup(eglTestCtx, "api", "EGLImage API tests") 657 { 658 } 659 660 void init (void) 661 { 662 addChild(new Image::InvalidCreateImage(m_eglTestCtx)); 663 664 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGB)); 665 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA)); 666 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_2D_KHR, GL_RGBA, true)); 667 668 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGB)); 669 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA)); 670 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR, GL_RGBA, true)); 671 672 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR, GL_RGBA)); 673 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR, GL_RGBA)); 674 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR, GL_RGBA)); 675 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR, GL_RGBA)); 676 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR, GL_RGBA)); 677 678 static const GLenum rboStorages[] = 679 { 680 GL_DEPTH_COMPONENT16, 681 GL_RGBA4, 682 GL_RGB5_A1, 683 GL_RGB565, 684 GL_STENCIL_INDEX8 685 }; 686 for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(rboStorages); storageNdx++) 687 addChild(new Image::CreateImageGLES2(m_eglTestCtx, EGL_GL_RENDERBUFFER_KHR, rboStorages[storageNdx])); 688 689 addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_TEXTURE_2D)); 690 addChild(new Image::ImageTargetGLES2(m_eglTestCtx, GL_RENDERBUFFER)); 691 } 692 }; 693 694 } // Image 695 696 ImageTests::ImageTests (EglTestContext& eglTestCtx) 697 : TestCaseGroup(eglTestCtx, "image", "EGLImage Tests") 698 { 699 } 700 701 ImageTests::~ImageTests (void) 702 { 703 } 704 705 void ImageTests::init (void) 706 { 707 addChild(new Image::ApiTests(m_eglTestCtx)); 708 addChild(new Image::SimpleCreationTests(m_eglTestCtx)); 709 addChild(new Image::ModifyTests(m_eglTestCtx)); 710 addChild(new Image::MultiContextRenderTests(m_eglTestCtx)); 711 } 712 713 } // egl 714 } // deqp 715