Path: blob/21.2-virgl/src/gallium/targets/osmesa/test-render.cpp
4565 views
#include <cstdint>1#include <cstdio>2#include <cstdlib>3#include <array>4#include <memory>56#include <gtest/gtest.h>78#include "GL/osmesa.h"9#include "util/macros.h"10#include "util/u_endian.h"11#include "util/u_math.h"1213typedef struct {14unsigned format;15GLenum type;16int bpp;17uint64_t expected;18} Params;1920class OSMesaRenderTestFixture : public testing::TestWithParam<Params> {};2122std::string23name_params(const testing::TestParamInfo<Params> params) {24auto p = params.param;25std::string first, second;26switch (p.format) {27case OSMESA_RGBA:28first = "rgba";29break;30case OSMESA_BGRA:31first = "bgra";32break;33case OSMESA_RGB:34first = "rgb";35break;36case OSMESA_RGB_565:37first = "rgb_565";38break;39case OSMESA_ARGB:40first = "argb";41break;42}4344switch (p.type) {45case GL_UNSIGNED_SHORT:46second = "unsigned_short";47break;48case GL_UNSIGNED_BYTE:49second = "unsigned_byte";50break;51case GL_FLOAT:52second = "float";53break;54case GL_UNSIGNED_SHORT_5_6_5:55second = "unsigned_short_565";56break;57}5859return first + "_" + second;60};6162TEST_P(OSMesaRenderTestFixture, Render)63{64auto p = GetParam();65const int w = 2, h = 2;66uint8_t pixels[w * h * 8] = { 0 };6768std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{69OSMesaCreateContext(p.format, NULL), &OSMesaDestroyContext};70ASSERT_TRUE(ctx);7172auto ret = OSMesaMakeCurrent(ctx.get(), &pixels, p.type, w, h);73ASSERT_EQ(ret, GL_TRUE);7475glClearColor(0.25, 1.0, 0.5, 0.75);7677uint64_t expected = p.expected;7879/* All the formats other than 565 and RGB/byte are array formats, but our80* expected values are packed, so byte swap appropriately.81*/82if (UTIL_ARCH_BIG_ENDIAN) {83switch (p.bpp) {84case 8:85expected = util_bswap64(expected);86break;8788case 4:89expected = util_bswap32(expected);90break;9192case 3:93case 2:94break;95}96}9798glClear(GL_COLOR_BUFFER_BIT);99glFinish();100101#if 0 /* XXX */102for (unsigned i = 0; i < ARRAY_SIZE(pixels); i += 4) {103fprintf(stderr, "pixel %d: %02x %02x %02x %02x\n",104i / 4,105pixels[i + 0],106pixels[i + 1],107pixels[i + 2],108pixels[i + 3]);109}110#endif111112for (unsigned i = 0; i < w * h; i++) {113switch (p.bpp) {114case 2: {115uint16_t color = 0;116memcpy(&color, &pixels[i * p.bpp], p.bpp);117ASSERT_EQ(expected, color);118break;119}120121case 3: {122uint32_t color = ((pixels[i * p.bpp + 0] << 0) |123(pixels[i * p.bpp + 1] << 8) |124(pixels[i * p.bpp + 2] << 16));125ASSERT_EQ(expected, color);126break;127}128129case 4: {130uint32_t color = 0;131memcpy(&color, &pixels[i * p.bpp], p.bpp);132ASSERT_EQ(expected, color);133break;134}135136case 8: {137uint64_t color = 0;138memcpy(&color, &pixels[i * p.bpp], p.bpp);139ASSERT_EQ(expected, color);140break;141}142143default:144unreachable("bad bpp");145}146}147}148149INSTANTIATE_TEST_CASE_P(150OSMesaRenderTest,151OSMesaRenderTestFixture,152testing::Values(153Params{ OSMESA_RGBA, GL_UNSIGNED_BYTE, 4, 0xbf80ff40 },154Params{ OSMESA_BGRA, GL_UNSIGNED_BYTE, 4, 0xbf40ff80 },155Params{ OSMESA_ARGB, GL_UNSIGNED_BYTE, 4, 0x80ff40bf},156Params{ OSMESA_RGB, GL_UNSIGNED_BYTE, 3, 0x80ff40 },157Params{ OSMESA_RGBA, GL_UNSIGNED_SHORT, 8, 0xbfff8000ffff4000ull },158Params{ OSMESA_RGB_565, GL_UNSIGNED_SHORT_5_6_5, 2, ((0x10 << 0) |159(0x3f << 5) |160(0x8 << 11)) }161),162name_params163);164165TEST(OSMesaRenderTest, depth)166{167std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{168OSMesaCreateContextExt(OSMESA_RGB_565, 24, 8, 0, NULL), &OSMesaDestroyContext};169ASSERT_TRUE(ctx);170171const int w = 3, h = 2;172uint8_t pixels[4096 * h * 2] = {0}; /* different cpp from our depth! */173auto ret = OSMesaMakeCurrent(ctx.get(), &pixels, GL_UNSIGNED_SHORT_5_6_5, w, h);174ASSERT_EQ(ret, GL_TRUE);175176/* Expand the row length for the color buffer so we can see that it doesn't affect depth. */177OSMesaPixelStore(OSMESA_ROW_LENGTH, 4096);178179uint32_t *depth;180GLint dw, dh, depth_cpp;181ASSERT_EQ(true, OSMesaGetDepthBuffer(ctx.get(), &dw, &dh, &depth_cpp, (void **)&depth));182183ASSERT_EQ(dw, w);184ASSERT_EQ(dh, h);185ASSERT_EQ(depth_cpp, 4);186187glClearDepth(1.0);188glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);189glFinish();190EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff);191EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff);192EXPECT_EQ(depth[w * 1 + 0], 0x00ffffff);193EXPECT_EQ(depth[w * 1 + 1], 0x00ffffff);194195/* Scissor to the top half and clear */196glEnable(GL_SCISSOR_TEST);197glScissor(0, 1, 2, 1);198glClearDepth(0.0);199glClear(GL_DEPTH_BUFFER_BIT);200glFinish();201EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff);202EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff);203EXPECT_EQ(depth[w * 1 + 0], 0x00000000);204EXPECT_EQ(depth[w * 1 + 1], 0x00000000);205206/* Y_UP didn't affect depth buffer orientation in classic osmesa. */207OSMesaPixelStore(OSMESA_Y_UP, false);208glScissor(0, 1, 1, 1);209glClearDepth(1.0);210glClear(GL_DEPTH_BUFFER_BIT);211glFinish();212EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff);213EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff);214EXPECT_EQ(depth[w * 1 + 0], 0x00ffffff);215EXPECT_EQ(depth[w * 1 + 1], 0x00000000);216}217218TEST(OSMesaRenderTest, depth_get_no_attachment)219{220std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{221OSMesaCreateContextExt(OSMESA_RGBA, 0, 0, 0, NULL), &OSMesaDestroyContext};222ASSERT_TRUE(ctx);223224uint32_t pixel;225auto ret = OSMesaMakeCurrent(ctx.get(), &pixel, GL_UNSIGNED_BYTE, 1, 1);226ASSERT_EQ(ret, GL_TRUE);227228uint32_t *depth;229GLint dw = 1, dh = 1, depth_cpp = 1;230ASSERT_EQ(false, OSMesaGetDepthBuffer(ctx.get(), &dw, &dh, &depth_cpp, (void **)&depth));231ASSERT_EQ(depth_cpp, NULL);232ASSERT_EQ(dw, 0);233ASSERT_EQ(dh, 0);234ASSERT_EQ(depth_cpp, 0);235}236237static uint32_t be_bswap32(uint32_t x)238{239if (UTIL_ARCH_BIG_ENDIAN)240return util_bswap32(x);241else242return x;243}244245TEST(OSMesaRenderTest, separate_buffers_per_context)246{247std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx1{248OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext};249std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx2{250OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext};251ASSERT_TRUE(ctx1);252ASSERT_TRUE(ctx2);253254uint32_t pixel1, pixel2;255256ASSERT_EQ(OSMesaMakeCurrent(ctx1.get(), &pixel1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE);257glClearColor(1.0, 0.0, 0.0, 0.0);258glClear(GL_COLOR_BUFFER_BIT);259glFinish();260EXPECT_EQ(pixel1, be_bswap32(0x000000ff));261262ASSERT_EQ(OSMesaMakeCurrent(ctx2.get(), &pixel2, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE);263glClearColor(0.0, 1.0, 0.0, 0.0);264glClear(GL_COLOR_BUFFER_BIT);265glFinish();266EXPECT_EQ(pixel1, be_bswap32(0x000000ff));267EXPECT_EQ(pixel2, be_bswap32(0x0000ff00));268269/* Leave a dangling render to pixel2 as we switch contexts (there should be270*/271glClearColor(0.0, 0.0, 1.0, 0.0);272glClear(GL_COLOR_BUFFER_BIT);273274ASSERT_EQ(OSMesaMakeCurrent(ctx1.get(), &pixel1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE);275/* Draw something off screen to trigger a real flush. We should have the276* same contents in pixel1 as before277*/278glBegin(GL_TRIANGLES);279glVertex2f(-2, -2);280glVertex2f(-2, -2);281glVertex2f(-2, -2);282glEnd();283glFinish();284EXPECT_EQ(pixel1, be_bswap32(0x000000ff));285EXPECT_EQ(pixel2, be_bswap32(0x00ff0000));286}287288289