17ec681f3Smrg#include <cstdint> 27ec681f3Smrg#include <cstdio> 37ec681f3Smrg#include <cstdlib> 47ec681f3Smrg#include <array> 57ec681f3Smrg#include <memory> 67ec681f3Smrg 77ec681f3Smrg#include <gtest/gtest.h> 87ec681f3Smrg 97ec681f3Smrg#include "GL/osmesa.h" 107ec681f3Smrg#include "util/macros.h" 117ec681f3Smrg#include "util/u_endian.h" 127ec681f3Smrg#include "util/u_math.h" 137ec681f3Smrg 147ec681f3Smrgtypedef struct { 157ec681f3Smrg unsigned format; 167ec681f3Smrg GLenum type; 177ec681f3Smrg int bpp; 187ec681f3Smrg uint64_t expected; 197ec681f3Smrg} Params; 207ec681f3Smrg 217ec681f3Smrgclass OSMesaRenderTestFixture : public testing::TestWithParam<Params> {}; 227ec681f3Smrg 237ec681f3Smrgstd::string 247ec681f3Smrgname_params(const testing::TestParamInfo<Params> params) { 257ec681f3Smrg auto p = params.param; 267ec681f3Smrg std::string first, second; 277ec681f3Smrg switch (p.format) { 287ec681f3Smrg case OSMESA_RGBA: 297ec681f3Smrg first = "rgba"; 307ec681f3Smrg break; 317ec681f3Smrg case OSMESA_BGRA: 327ec681f3Smrg first = "bgra"; 337ec681f3Smrg break; 347ec681f3Smrg case OSMESA_RGB: 357ec681f3Smrg first = "rgb"; 367ec681f3Smrg break; 377ec681f3Smrg case OSMESA_RGB_565: 387ec681f3Smrg first = "rgb_565"; 397ec681f3Smrg break; 407ec681f3Smrg case OSMESA_ARGB: 417ec681f3Smrg first = "argb"; 427ec681f3Smrg break; 437ec681f3Smrg } 447ec681f3Smrg 457ec681f3Smrg switch (p.type) { 467ec681f3Smrg case GL_UNSIGNED_SHORT: 477ec681f3Smrg second = "unsigned_short"; 487ec681f3Smrg break; 497ec681f3Smrg case GL_UNSIGNED_BYTE: 507ec681f3Smrg second = "unsigned_byte"; 517ec681f3Smrg break; 527ec681f3Smrg case GL_FLOAT: 537ec681f3Smrg second = "float"; 547ec681f3Smrg break; 557ec681f3Smrg case GL_UNSIGNED_SHORT_5_6_5: 567ec681f3Smrg second = "unsigned_short_565"; 577ec681f3Smrg break; 587ec681f3Smrg } 597ec681f3Smrg 607ec681f3Smrg return first + "_" + second; 617ec681f3Smrg}; 627ec681f3Smrg 637ec681f3SmrgTEST_P(OSMesaRenderTestFixture, Render) 647ec681f3Smrg{ 657ec681f3Smrg auto p = GetParam(); 667ec681f3Smrg const int w = 2, h = 2; 677ec681f3Smrg uint8_t pixels[w * h * 8] = { 0 }; 687ec681f3Smrg 697ec681f3Smrg std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{ 707ec681f3Smrg OSMesaCreateContext(p.format, NULL), &OSMesaDestroyContext}; 717ec681f3Smrg ASSERT_TRUE(ctx); 727ec681f3Smrg 737ec681f3Smrg auto ret = OSMesaMakeCurrent(ctx.get(), &pixels, p.type, w, h); 747ec681f3Smrg ASSERT_EQ(ret, GL_TRUE); 757ec681f3Smrg 767ec681f3Smrg glClearColor(0.25, 1.0, 0.5, 0.75); 777ec681f3Smrg 787ec681f3Smrg uint64_t expected = p.expected; 797ec681f3Smrg 807ec681f3Smrg /* All the formats other than 565 and RGB/byte are array formats, but our 817ec681f3Smrg * expected values are packed, so byte swap appropriately. 827ec681f3Smrg */ 837ec681f3Smrg if (UTIL_ARCH_BIG_ENDIAN) { 847ec681f3Smrg switch (p.bpp) { 857ec681f3Smrg case 8: 867ec681f3Smrg expected = util_bswap64(expected); 877ec681f3Smrg break; 887ec681f3Smrg 897ec681f3Smrg case 4: 907ec681f3Smrg expected = util_bswap32(expected); 917ec681f3Smrg break; 927ec681f3Smrg 937ec681f3Smrg case 3: 947ec681f3Smrg case 2: 957ec681f3Smrg break; 967ec681f3Smrg } 977ec681f3Smrg } 987ec681f3Smrg 997ec681f3Smrg glClear(GL_COLOR_BUFFER_BIT); 1007ec681f3Smrg glFinish(); 1017ec681f3Smrg 1027ec681f3Smrg#if 0 /* XXX */ 1037ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(pixels); i += 4) { 1047ec681f3Smrg fprintf(stderr, "pixel %d: %02x %02x %02x %02x\n", 1057ec681f3Smrg i / 4, 1067ec681f3Smrg pixels[i + 0], 1077ec681f3Smrg pixels[i + 1], 1087ec681f3Smrg pixels[i + 2], 1097ec681f3Smrg pixels[i + 3]); 1107ec681f3Smrg } 1117ec681f3Smrg#endif 1127ec681f3Smrg 1137ec681f3Smrg for (unsigned i = 0; i < w * h; i++) { 1147ec681f3Smrg switch (p.bpp) { 1157ec681f3Smrg case 2: { 1167ec681f3Smrg uint16_t color = 0; 1177ec681f3Smrg memcpy(&color, &pixels[i * p.bpp], p.bpp); 1187ec681f3Smrg ASSERT_EQ(expected, color); 1197ec681f3Smrg break; 1207ec681f3Smrg } 1217ec681f3Smrg 1227ec681f3Smrg case 3: { 1237ec681f3Smrg uint32_t color = ((pixels[i * p.bpp + 0] << 0) | 1247ec681f3Smrg (pixels[i * p.bpp + 1] << 8) | 1257ec681f3Smrg (pixels[i * p.bpp + 2] << 16)); 1267ec681f3Smrg ASSERT_EQ(expected, color); 1277ec681f3Smrg break; 1287ec681f3Smrg } 1297ec681f3Smrg 1307ec681f3Smrg case 4: { 1317ec681f3Smrg uint32_t color = 0; 1327ec681f3Smrg memcpy(&color, &pixels[i * p.bpp], p.bpp); 1337ec681f3Smrg ASSERT_EQ(expected, color); 1347ec681f3Smrg break; 1357ec681f3Smrg } 1367ec681f3Smrg 1377ec681f3Smrg case 8: { 1387ec681f3Smrg uint64_t color = 0; 1397ec681f3Smrg memcpy(&color, &pixels[i * p.bpp], p.bpp); 1407ec681f3Smrg ASSERT_EQ(expected, color); 1417ec681f3Smrg break; 1427ec681f3Smrg } 1437ec681f3Smrg 1447ec681f3Smrg default: 1457ec681f3Smrg unreachable("bad bpp"); 1467ec681f3Smrg } 1477ec681f3Smrg } 1487ec681f3Smrg} 1497ec681f3Smrg 1507ec681f3SmrgINSTANTIATE_TEST_CASE_P( 1517ec681f3Smrg OSMesaRenderTest, 1527ec681f3Smrg OSMesaRenderTestFixture, 1537ec681f3Smrg testing::Values( 1547ec681f3Smrg Params{ OSMESA_RGBA, GL_UNSIGNED_BYTE, 4, 0xbf80ff40 }, 1557ec681f3Smrg Params{ OSMESA_BGRA, GL_UNSIGNED_BYTE, 4, 0xbf40ff80 }, 1567ec681f3Smrg Params{ OSMESA_ARGB, GL_UNSIGNED_BYTE, 4, 0x80ff40bf}, 1577ec681f3Smrg Params{ OSMESA_RGB, GL_UNSIGNED_BYTE, 3, 0x80ff40 }, 1587ec681f3Smrg Params{ OSMESA_RGBA, GL_UNSIGNED_SHORT, 8, 0xbfff8000ffff4000ull }, 1597ec681f3Smrg Params{ OSMESA_RGB_565, GL_UNSIGNED_SHORT_5_6_5, 2, ((0x10 << 0) | 1607ec681f3Smrg (0x3f << 5) | 1617ec681f3Smrg (0x8 << 11)) } 1627ec681f3Smrg ), 1637ec681f3Smrg name_params 1647ec681f3Smrg); 1657ec681f3Smrg 1667ec681f3SmrgTEST(OSMesaRenderTest, depth) 1677ec681f3Smrg{ 1687ec681f3Smrg std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{ 1697ec681f3Smrg OSMesaCreateContextExt(OSMESA_RGB_565, 24, 8, 0, NULL), &OSMesaDestroyContext}; 1707ec681f3Smrg ASSERT_TRUE(ctx); 1717ec681f3Smrg 1727ec681f3Smrg const int w = 3, h = 2; 1737ec681f3Smrg uint8_t pixels[4096 * h * 2] = {0}; /* different cpp from our depth! */ 1747ec681f3Smrg auto ret = OSMesaMakeCurrent(ctx.get(), &pixels, GL_UNSIGNED_SHORT_5_6_5, w, h); 1757ec681f3Smrg ASSERT_EQ(ret, GL_TRUE); 1767ec681f3Smrg 1777ec681f3Smrg /* Expand the row length for the color buffer so we can see that it doesn't affect depth. */ 1787ec681f3Smrg OSMesaPixelStore(OSMESA_ROW_LENGTH, 4096); 1797ec681f3Smrg 1807ec681f3Smrg uint32_t *depth; 1817ec681f3Smrg GLint dw, dh, depth_cpp; 1827ec681f3Smrg ASSERT_EQ(true, OSMesaGetDepthBuffer(ctx.get(), &dw, &dh, &depth_cpp, (void **)&depth)); 1837ec681f3Smrg 1847ec681f3Smrg ASSERT_EQ(dw, w); 1857ec681f3Smrg ASSERT_EQ(dh, h); 1867ec681f3Smrg ASSERT_EQ(depth_cpp, 4); 1877ec681f3Smrg 1887ec681f3Smrg glClearDepth(1.0); 1897ec681f3Smrg glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 1907ec681f3Smrg glFinish(); 1917ec681f3Smrg EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff); 1927ec681f3Smrg EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff); 1937ec681f3Smrg EXPECT_EQ(depth[w * 1 + 0], 0x00ffffff); 1947ec681f3Smrg EXPECT_EQ(depth[w * 1 + 1], 0x00ffffff); 1957ec681f3Smrg 1967ec681f3Smrg /* Scissor to the top half and clear */ 1977ec681f3Smrg glEnable(GL_SCISSOR_TEST); 1987ec681f3Smrg glScissor(0, 1, 2, 1); 1997ec681f3Smrg glClearDepth(0.0); 2007ec681f3Smrg glClear(GL_DEPTH_BUFFER_BIT); 2017ec681f3Smrg glFinish(); 2027ec681f3Smrg EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff); 2037ec681f3Smrg EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff); 2047ec681f3Smrg EXPECT_EQ(depth[w * 1 + 0], 0x00000000); 2057ec681f3Smrg EXPECT_EQ(depth[w * 1 + 1], 0x00000000); 2067ec681f3Smrg 2077ec681f3Smrg /* Y_UP didn't affect depth buffer orientation in classic osmesa. */ 2087ec681f3Smrg OSMesaPixelStore(OSMESA_Y_UP, false); 2097ec681f3Smrg glScissor(0, 1, 1, 1); 2107ec681f3Smrg glClearDepth(1.0); 2117ec681f3Smrg glClear(GL_DEPTH_BUFFER_BIT); 2127ec681f3Smrg glFinish(); 2137ec681f3Smrg EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff); 2147ec681f3Smrg EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff); 2157ec681f3Smrg EXPECT_EQ(depth[w * 1 + 0], 0x00ffffff); 2167ec681f3Smrg EXPECT_EQ(depth[w * 1 + 1], 0x00000000); 2177ec681f3Smrg} 2187ec681f3Smrg 2197ec681f3SmrgTEST(OSMesaRenderTest, depth_get_no_attachment) 2207ec681f3Smrg{ 2217ec681f3Smrg std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{ 2227ec681f3Smrg OSMesaCreateContextExt(OSMESA_RGBA, 0, 0, 0, NULL), &OSMesaDestroyContext}; 2237ec681f3Smrg ASSERT_TRUE(ctx); 2247ec681f3Smrg 2257ec681f3Smrg uint32_t pixel; 2267ec681f3Smrg auto ret = OSMesaMakeCurrent(ctx.get(), &pixel, GL_UNSIGNED_BYTE, 1, 1); 2277ec681f3Smrg ASSERT_EQ(ret, GL_TRUE); 2287ec681f3Smrg 2297ec681f3Smrg uint32_t *depth; 2307ec681f3Smrg GLint dw = 1, dh = 1, depth_cpp = 1; 2317ec681f3Smrg ASSERT_EQ(false, OSMesaGetDepthBuffer(ctx.get(), &dw, &dh, &depth_cpp, (void **)&depth)); 2327ec681f3Smrg ASSERT_EQ(depth_cpp, NULL); 2337ec681f3Smrg ASSERT_EQ(dw, 0); 2347ec681f3Smrg ASSERT_EQ(dh, 0); 2357ec681f3Smrg ASSERT_EQ(depth_cpp, 0); 2367ec681f3Smrg} 2377ec681f3Smrg 2387ec681f3Smrgstatic uint32_t be_bswap32(uint32_t x) 2397ec681f3Smrg{ 2407ec681f3Smrg if (UTIL_ARCH_BIG_ENDIAN) 2417ec681f3Smrg return util_bswap32(x); 2427ec681f3Smrg else 2437ec681f3Smrg return x; 2447ec681f3Smrg} 2457ec681f3Smrg 2467ec681f3SmrgTEST(OSMesaRenderTest, separate_buffers_per_context) 2477ec681f3Smrg{ 2487ec681f3Smrg std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx1{ 2497ec681f3Smrg OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext}; 2507ec681f3Smrg std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx2{ 2517ec681f3Smrg OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext}; 2527ec681f3Smrg ASSERT_TRUE(ctx1); 2537ec681f3Smrg ASSERT_TRUE(ctx2); 2547ec681f3Smrg 2557ec681f3Smrg uint32_t pixel1, pixel2; 2567ec681f3Smrg 2577ec681f3Smrg ASSERT_EQ(OSMesaMakeCurrent(ctx1.get(), &pixel1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE); 2587ec681f3Smrg glClearColor(1.0, 0.0, 0.0, 0.0); 2597ec681f3Smrg glClear(GL_COLOR_BUFFER_BIT); 2607ec681f3Smrg glFinish(); 2617ec681f3Smrg EXPECT_EQ(pixel1, be_bswap32(0x000000ff)); 2627ec681f3Smrg 2637ec681f3Smrg ASSERT_EQ(OSMesaMakeCurrent(ctx2.get(), &pixel2, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE); 2647ec681f3Smrg glClearColor(0.0, 1.0, 0.0, 0.0); 2657ec681f3Smrg glClear(GL_COLOR_BUFFER_BIT); 2667ec681f3Smrg glFinish(); 2677ec681f3Smrg EXPECT_EQ(pixel1, be_bswap32(0x000000ff)); 2687ec681f3Smrg EXPECT_EQ(pixel2, be_bswap32(0x0000ff00)); 2697ec681f3Smrg 2707ec681f3Smrg /* Leave a dangling render to pixel2 as we switch contexts (there should be 2717ec681f3Smrg */ 2727ec681f3Smrg glClearColor(0.0, 0.0, 1.0, 0.0); 2737ec681f3Smrg glClear(GL_COLOR_BUFFER_BIT); 2747ec681f3Smrg 2757ec681f3Smrg ASSERT_EQ(OSMesaMakeCurrent(ctx1.get(), &pixel1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE); 2767ec681f3Smrg /* Draw something off screen to trigger a real flush. We should have the 2777ec681f3Smrg * same contents in pixel1 as before 2787ec681f3Smrg */ 2797ec681f3Smrg glBegin(GL_TRIANGLES); 2807ec681f3Smrg glVertex2f(-2, -2); 2817ec681f3Smrg glVertex2f(-2, -2); 2827ec681f3Smrg glVertex2f(-2, -2); 2837ec681f3Smrg glEnd(); 2847ec681f3Smrg glFinish(); 2857ec681f3Smrg EXPECT_EQ(pixel1, be_bswap32(0x000000ff)); 2867ec681f3Smrg EXPECT_EQ(pixel2, be_bswap32(0x00ff0000)); 2877ec681f3Smrg} 2887ec681f3Smrg 2897ec681f3SmrgTEST(OSMesaRenderTest, resize) 2907ec681f3Smrg{ 2917ec681f3Smrg std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{ 2927ec681f3Smrg OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext}; 2937ec681f3Smrg ASSERT_TRUE(ctx); 2947ec681f3Smrg 2957ec681f3Smrg uint32_t draw1[1], draw2[4]; 2967ec681f3Smrg 2977ec681f3Smrg ASSERT_EQ(OSMesaMakeCurrent(ctx.get(), draw1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE); 2987ec681f3Smrg glClearColor(1.0, 0.0, 0.0, 0.0); 2997ec681f3Smrg glClear(GL_COLOR_BUFFER_BIT); 3007ec681f3Smrg glFinish(); 3017ec681f3Smrg EXPECT_EQ(draw1[0], be_bswap32(0x000000ff)); 3027ec681f3Smrg 3037ec681f3Smrg ASSERT_EQ(OSMesaMakeCurrent(ctx.get(), draw2, GL_UNSIGNED_BYTE, 2, 2), GL_TRUE); 3047ec681f3Smrg glClearColor(0.0, 1.0, 0.0, 0.0); 3057ec681f3Smrg glClear(GL_COLOR_BUFFER_BIT); 3067ec681f3Smrg glFinish(); 3077ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(draw2); i++) 3087ec681f3Smrg EXPECT_EQ(draw2[i], be_bswap32(0x0000ff00)); 3097ec681f3Smrg EXPECT_EQ(draw1[0], be_bswap32(0x000000ff)); 3107ec681f3Smrg} 311