diff options
author | Eric Anholt <eric@anholt.net> | 2009-02-16 15:23:39 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-03-07 03:30:55 -0800 |
commit | aa7c71facfe968af8f82c5a07b02cad039a3134e (patch) | |
tree | 9d6b0f210d05ec689520e7db6f1634845f3d91c1 /tests | |
parent | a2c35c6fe4b81bd9516ece02ca209dc0bbb2a9f0 (diff) |
Update glean tests to CVS HEAD from 2009-03-07.
Diffstat (limited to 'tests')
43 files changed, 4004 insertions, 81 deletions
diff --git a/tests/all.tests b/tests/all.tests index 8184e9c18..a83b4b51e 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -68,7 +68,11 @@ glean['texCube'] = GleanTest('texCube') glean['texEnv'] = GleanTest('texEnv') glean['texgen'] = GleanTest('texgen') glean['texRect'] = GleanTest('texRect') +glean['texcombine4'] = GleanTest('texcombine4') +glean['texswizzle'] = GleanTest('texswizzle') glean['texture_srgb'] = GleanTest('texture_srgb') +glean['texunits'] = GleanTest('texunits') +glean['vertarraybgra'] = GleanTest('vertarraybgra') glean['vertattrib'] = GleanTest('vertattrib') glean['vertProg1'] = GleanTest('vertProg1') diff --git a/tests/glean/CMakeLists.txt b/tests/glean/CMakeLists.txt index 67a1696b1..dd5650ead 100644 --- a/tests/glean/CMakeLists.txt +++ b/tests/glean/CMakeLists.txt @@ -46,11 +46,15 @@ add_executable (glean tscissor.cpp tteapot.cpp ttexcombine.cpp + ttexcombine4.cpp ttexcube.cpp ttexenv.cpp ttexgen.cpp ttexrect.cpp + ttexswizzle.cpp ttexture_srgb.cpp + ttexunits.cpp + tvertarraybgra.cpp tvertattrib.cpp tvertprog1.cpp tvtxperf.cpp diff --git a/tests/glean/dsconfig.cpp b/tests/glean/dsconfig.cpp index 88f9a81b1..861c0c831 100644 --- a/tests/glean/dsconfig.cpp +++ b/tests/glean/dsconfig.cpp @@ -2,6 +2,8 @@ // // Copyright (C) 1999 Allen Akin All Rights Reserved. // +// multisample changes: Copyright (c) 2008 VMware, Inc. All rights reserved. +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -31,9 +33,9 @@ #include "dsconfig.h" #include <iostream> #include <strstream> -#include <cstring> +#include <string.h> #include <map> -#include <climits> +#include <limits.h> #ifdef __WIN__ // disable the annoying warning : "forcing value to bool 'true' or 'false' (performance warning)" @@ -100,6 +102,7 @@ typedef enum { // These variable tags are used as array indices, VACCUMG, VACCUMB, VACCUMA, + VSAMPLES, VCANWINDOW, VCANPIXMAP, VCANPBUFFER, @@ -138,6 +141,7 @@ struct {CanonVar var; char* name;} varNames[] = { {VACCUMG, "accumG"}, {VACCUMB, "accumB"}, {VACCUMA, "accumA"}, + {VSAMPLES, "multisample"}, {VCANWINDOW, "window"}, {VCANPIXMAP, "pixmap"}, {VCANPBUFFER, "pBuffer"}, @@ -228,6 +232,18 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(::Display* dpy, ::XVisualInfo* pvi) { } else accR = accG = accB = accA = 0; + // Note that samples=0 means no multisampling! + // One might think that one sample per pixel means non-multisampling + // but that's not the convention used here. + samples = 0; + if (canRGBA) { + int sampBuf = 0; + glXGetConfig(dpy, vi, GLX_SAMPLE_BUFFERS, &sampBuf); + if (sampBuf) { + glXGetConfig(dpy, vi, GLX_SAMPLES, &samples); + } + } + canWindow = canPixmap = true; // Only guaranteed in early versions of GLX. @@ -329,6 +345,8 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::PIXELFORMATDESCRIPTOR *ppfd accB = pfd->cAccumBlueBits; accA = pfd->cAccumAlphaBits; + samples = 0; // XXX implement properly for Windows! + canWindow = pfd->dwFlags & PFD_DRAW_TO_WINDOW; canWinSysRender = pfd->dwFlags & PFD_SUPPORT_GDI; @@ -378,6 +396,7 @@ DrawingSurfaceConfig::DrawingSurfaceConfig() { accB = 32; accA = 32; + samples = 0; canWindow = 1; canWinSysRender = 1; @@ -436,6 +455,8 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::AGLPixelFormat pfd) else r = g = b = a = 0; + samples = 0; // XXX implement properly for AGL + aglDescribePixelFormat( pf, AGL_DEPTH_SIZE, (long *)& z); aglDescribePixelFormat( pf, AGL_STENCIL_SIZE, (long *)& s); @@ -544,6 +565,9 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(string& str) { case VACCUMA: accA = lex.iValue; break; + case VSAMPLES: + samples = lex.iValue; + break; case VCANWINDOW: canWindow = lex.iValue; break; @@ -668,6 +692,8 @@ DrawingSurfaceConfig::canonicalDescription() { << ' ' << mapVarToName[VACCUMB] << ' ' << accB << ' ' << mapVarToName[VACCUMA] << ' ' << accA; + s << ' ' << mapVarToName[VSAMPLES] << ' ' << samples; + s << ' ' << mapVarToName[VCANWINDOW] << ' ' << canWindow; # if defined(__X11__) @@ -768,6 +794,10 @@ DrawingSurfaceConfig::conciseDescription() { } } + if (samples) { + s << ", samples" << samples; + } + { s << ", "; bool sep = false; @@ -868,6 +898,10 @@ DrawingSurfaceConfig::match(vector<DrawingSurfaceConfig*>& choices) { error += abs(accB - c.accB); if (accA && c.accA) error += abs(accA - c.accA); + // Use a huge error value for multisample mismatch. + // Not sure this is the best solution. + if (samples != c.samples) + error += 1000; if (error < bestError) { bestError = error; diff --git a/tests/glean/dsconfig.h b/tests/glean/dsconfig.h index a5f24f925..ea7ffd7cf 100644 --- a/tests/glean/dsconfig.h +++ b/tests/glean/dsconfig.h @@ -1,6 +1,8 @@ // BEGIN_COPYRIGHT // // Copyright (C) 1999 Allen Akin All Rights Reserved. +// +// multisample changes: Copyright (c) 2008 VMware, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -135,6 +137,9 @@ class DrawingSurfaceConfig { int accA; // Depth of accum buf alpha channel. + int samples; // Number of samples per pixel. + // Zero indicates a non-ms config. + bool canWindow; // True if can be used for windows. # if defined(__X11__) diff --git a/tests/glean/dsfilt.cpp b/tests/glean/dsfilt.cpp index 9227bc6fe..6b1795b42 100644 --- a/tests/glean/dsfilt.cpp +++ b/tests/glean/dsfilt.cpp @@ -2,6 +2,8 @@ // // Copyright (C) 1999 Allen Akin All Rights Reserved. // +// multisample changes: Copyright (c) 2008 VMware, Inc. All rights reserved. +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -214,6 +216,7 @@ DrawingSurfaceFilter::InitVarTable() { varTable["accuma"] = VAR_ACCUM_A; varTable["accumrgb"] = VAR_ACCUM_RGB; varTable["accumrgba"] = VAR_ACCUM_RGBA; + varTable["samples"] = VAR_SAMPLES; varTable["aux"] = VAR_AUX; varTable["db"] = VAR_DB; varTable["sb"] = VAR_SB; @@ -283,6 +286,9 @@ DrawingSurfaceFilter::FetchVariable(const DrawingSurfaceConfig& c, Token v) { case VAR_ACCUM_RGBA: return min(c.accR, min(c.accG, min(c.accB, c.accA))); + case VAR_SAMPLES: + return c.samples; + case VAR_AUX: return c.aux; diff --git a/tests/glean/dsfilt.h b/tests/glean/dsfilt.h index 89c6d5833..ec715759f 100644 --- a/tests/glean/dsfilt.h +++ b/tests/glean/dsfilt.h @@ -2,6 +2,8 @@ // // Copyright (C) 1999 Allen Akin All Rights Reserved. // +// multisample changes: Copyright (c) 2008 VMware, Inc. All rights reserved. +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -175,6 +177,8 @@ class DrawingSurfaceFilter { VAR_ACCUM_RGB, // min(accum r, accum g, accum b) VAR_ACCUM_RGBA, // min(accum r, accum g, accum b, accum a) + VAR_SAMPLES, // number of samples per pixel + VAR_AUX, // number of aux color buffers VAR_DB, // nonzero if double buffered diff --git a/tests/glean/environ.cpp b/tests/glean/environ.cpp index 39d8815c6..fac0f6690 100644 --- a/tests/glean/environ.cpp +++ b/tests/glean/environ.cpp @@ -39,6 +39,7 @@ #include <fcntl.h> #include <unistd.h> #include <errno.h> +#include <stdlib.h> #elif defined(__MS__) #include <sys/stat.h> diff --git a/tests/glean/glutils.cpp b/tests/glean/glutils.cpp index 4b38d6203..26d348831 100644 --- a/tests/glean/glutils.cpp +++ b/tests/glean/glutils.cpp @@ -32,6 +32,7 @@ // glutils.cpp: frequently-used OpenGL operations #define GLX_GLXEXT_PROTOTYPES +#include <stdlib.h> #include "glwrap.h" #include "environ.h" #include "lex.h" diff --git a/tests/glean/image.h b/tests/glean/image.h index 83942f4f7..fd28f49cb 100644 --- a/tests/glean/image.h +++ b/tests/glean/image.h @@ -223,7 +223,10 @@ class Image { BasicStats stats[4]; // stats for absolute error in // R, G, B, and A }; - Registration reg(Image& ref); + Registration reg(Image& img); + + // test if images are identical + bool operator==(const Image &ref) const; // Image arithmetic // XXX type and format conversions, with appropriate scaling. diff --git a/tests/glean/image_misc.cpp b/tests/glean/image_misc.cpp index adfdc2247..176267011 100644 --- a/tests/glean/image_misc.cpp +++ b/tests/glean/image_misc.cpp @@ -131,6 +131,32 @@ Image::~Image() { delete[] _pixels; } + +// Test if two images are identical +bool Image::operator==(const Image &img) const +{ + // cast away const because of rowSizeInBytes() + Image &img1 = const_cast<Image&>(*this); + Image &img2 = const_cast<Image&>(img); + + if (img1.width() != img2.width() || + img1.height() != img2.height() || + img1.format() != img2.format() || + img1.type() != img2.type() || + img1.alignment() != img2.alignment() || + img1.rowSizeInBytes() != img2.rowSizeInBytes()) + return false; + + const char *p1 = img1.pixels(); + const char *p2 = img2.pixels(); + const int n = img1.rowSizeInBytes() * img1.height(); + if (memcmp(p1, p2, n) != 0) + return false; + + return true; +} + + /////////////////////////////////////////////////////////////////////////////// // pixels - set pointer to pixel array /////////////////////////////////////////////////////////////////////////////// diff --git a/tests/glean/main.cpp b/tests/glean/main.cpp index b7a1d2d53..77fae4ff8 100644 --- a/tests/glean/main.cpp +++ b/tests/glean/main.cpp @@ -34,6 +34,7 @@ using namespace std; #include <cassert> +#include <cstring> #include <iostream> #include <string> #include <vector> diff --git a/tests/glean/tapi2.cpp b/tests/glean/tapi2.cpp index 795b4516b..8367d74d1 100644 --- a/tests/glean/tapi2.cpp +++ b/tests/glean/tapi2.cpp @@ -31,9 +31,11 @@ #define GL_GLEXT_PROTOTYPES -#include "tapi2.h" +#include <stdlib.h> +#include <cstring> #include <cassert> #include <math.h> +#include "tapi2.h" namespace GLEAN { @@ -281,7 +283,7 @@ API2Test::renderQuad(GLfloat *pixel) const glTexCoord2f(0, 1); glVertex2f(-r, r); glEnd(); - // read a pixel from lower-left corder of rendered quad + // read a pixel from lower-left corner of rendered quad glReadPixels(windowSize / 2 - 2, windowSize / 2 - 2, 1, 1, GL_RGBA, GL_FLOAT, pixel); } @@ -319,7 +321,7 @@ API2Test::renderQuadWithArrays(GLint attr, const GLfloat value[4], glDisable(GL_VERTEX_ARRAY); glDisableVertexAttribArray_func(attr); - // read a pixel from lower-left corder of rendered quad + // read a pixel from lower-left corner of rendered quad glReadPixels(windowSize / 2 - 2, windowSize / 2 - 2, 1, 1, GL_RGBA, GL_FLOAT, pixel); } @@ -702,7 +704,12 @@ API2Test::testUniformiFuncs(void) renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]i failed"); - //printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); +#if 0 + printf("Expected color %f %f %f %f\n", + expected[0], expected[1], expected[2], expected[3]); + printf("Found color %f %f %f %f\n", + pixel[0], pixel[1], pixel[2], pixel[3]); +#endif return false; } @@ -748,6 +755,14 @@ API2Test::testShaderAttribs(void) GLfloat pixel[4]; renderQuadWithArrays(attr, testColors[i], pixel); if (!equalColors(pixel, testColors[i])) { +#if 0 + printf("Expected color %f %f %f\n", + testColors[i][0], + testColors[i][1], + testColors[i][2]); + printf("Found color %f %f %f\n", + pixel[0], pixel[1], pixel[2]); +#endif REPORT_FAILURE("Vertex array test failed"); return false; } diff --git a/tests/glean/tbase.h b/tests/glean/tbase.h index afe539437..2cf72dd1e 100644 --- a/tests/glean/tbase.h +++ b/tests/glean/tbase.h @@ -125,6 +125,8 @@ and tbasic.cpp. class GLEAN::DrawingSurfaceConfig; // Forward reference. + +// Macro for constructor for Glean test taking width, height and one config flag #define GLEAN_CLASS_WHO(TEST, RESULT, WIDTH, HEIGHT, ONE) \ TEST(const char* aName, const char* aFilter, \ const char* aDescription): \ @@ -146,6 +148,7 @@ class GLEAN::DrawingSurfaceConfig; // Forward reference. BaseTest<RESULT>(aName, aFilter, anExtensionList, aDescription) { \ fWidth = WIDTH; \ fHeight = HEIGHT; \ + testOne = ONE; \ } \ virtual ~TEST() {} \ \ @@ -153,12 +156,16 @@ class GLEAN::DrawingSurfaceConfig; // Forward reference. virtual void compareOne(RESULT& oldR, RESULT& newR); \ virtual void logOne(RESULT& r) +// Macro for constructor for Glean test taking width, height #define GLEAN_CLASS_WH(TEST, RESULT, WIDTH, HEIGHT) \ GLEAN_CLASS_WHO(TEST, RESULT, WIDTH, HEIGHT, false) +// Macro for constructor for Glean test taking only test class and result class #define GLEAN_CLASS(TEST, RESULT) \ GLEAN_CLASS_WHO(TEST, RESULT, 258, 258, false) + + namespace GLEAN { class BaseResult : public Result { @@ -185,6 +192,8 @@ public: } }; + +// The BaseTest class is a templatized class taking a ResultType as a parameter template <class ResultType> class BaseTest: public Test { public: BaseTest(const char* aName, const char* aFilter, @@ -252,14 +261,23 @@ public: << '\n'; } + // This method allows a test to indicate that it's not applicable. + // For example, the GL version is too low. + virtual bool isApplicable() const { + return true; + } + virtual void run(Environment& environment) { - if (hasRun) return; // no multiple invocations + if (hasRun) + return; // no multiple invocations + // Invoke the prerequisite tests, if any: for (Test** t = prereqs; t != 0 && *t != 0; ++t) (*t)->run(environment); env = &environment; // make environment available logDescription(); // log invocation WindowSystem& ws = env->winSys; + try { OutputStream os(*this); // open results file @@ -275,8 +293,13 @@ public: ++p) { Window w(ws, **p, fWidth, fHeight); RenderingContext rc(ws, **p); - if (!ws.makeCurrent(rc, w)) - ; // XXX need to throw exception here + if (!ws.makeCurrent(rc, w)) { + // XXX need to throw exception here + } + + // Check if test is applicable to this context + if (!isApplicable()) + continue; // Check for all prerequisite extensions. Note // that this must be done after the rendering @@ -293,7 +316,10 @@ public: // Save the result results.push_back(r); r->put(os); - if (testOne) break; + + // if testOne, skip remaining surface configs + if (testOne) + break; } } catch (DrawingSurfaceFilter::Syntax e) { diff --git a/tests/glean/tblend.cpp b/tests/glean/tblend.cpp index 3fb8d6116..b94c82f48 100644 --- a/tests/glean/tblend.cpp +++ b/tests/glean/tblend.cpp @@ -29,6 +29,7 @@ // tblend.cpp: Test blending functions. #include <assert.h> +#include <stdlib.h> #include "tblend.h" #include "rand.h" #include "image.h" diff --git a/tests/glean/tdepthstencil.cpp b/tests/glean/tdepthstencil.cpp index 945d8bd1c..54e97df0f 100644 --- a/tests/glean/tdepthstencil.cpp +++ b/tests/glean/tdepthstencil.cpp @@ -30,12 +30,13 @@ // Brian Paul 1 October 2005 +#include <cassert> +#include <cmath> +#include <cstring> #include "tdepthstencil.h" #include "rand.h" #include "timer.h" #include "image.h" -#include <cassert> -#include <cmath> #ifdef GL_EXT_packed_depth_stencil diff --git a/tests/glean/tfbo.cpp b/tests/glean/tfbo.cpp index 24b03f5c1..ddfea1ccc 100644 --- a/tests/glean/tfbo.cpp +++ b/tests/glean/tfbo.cpp @@ -81,15 +81,21 @@ FBOTest::setup(void) tolerance[4] = 1.0; // Check if GL_EXT_framebuffer_object is supported - if (!strstr((char *) glGetString(GL_EXTENSIONS), "GL_EXT_framebuffer_object")) { + if (GLUtils::haveExtension("GL_EXT_framebuffer_object")) { + printf("GL_EXT_framebuffer_object is supported\n"); + useFramebuffer = 1; + } + else { printf("GL_EXT_framebuffer_object is not supported\n"); useFramebuffer = 0; return false; } - else { - printf("GL_EXT_framebuffer_object is supported\n"); - useFramebuffer = 1; - } + + haveARBfbo = GLUtils::haveExtension("GL_ARB_framebuffer_object"); + if (haveARBfbo) + printf("GL_ARB_framebuffer_object is supported\n"); + else + printf("GL_ARB_framebuffer_object is not supported\n"); return true; } @@ -1217,7 +1223,8 @@ FBOTest::testErrorHandling(void) return false; } - // All attached images have the same width and height + // All attached images have the same width and height, + // unless GL_ARB_framebuffer object is supported. glGenFramebuffersEXT(1, fbs); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); glGenTextures(2, textures); @@ -1238,15 +1245,16 @@ FBOTest::testErrorHandling(void) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, fbs); glDeleteTextures(2, textures); - if (status != GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT) { + if (!haveARBfbo && + status != GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT) { REPORT_FAILURE - ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"); + ("If renderbuffer sizes don't all match, status should be GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"); return false; } // All images attached to the attachment points - // COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT must have - // the same internal format. + // COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT must + // have the same internal format, unless ARB_fbo is supported. glGenFramebuffersEXT(1, fbs); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); glGenTextures(2, textures); @@ -1267,15 +1275,17 @@ FBOTest::testErrorHandling(void) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, fbs); glDeleteTextures(2, textures); - if (status != GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT) { + if (!haveARBfbo && + status != GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT) { REPORT_FAILURE - ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"); + ("All color renderbuffers must be of same format, status should be GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"); return false; } - // The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be - // NONE for any color attachment point(s) named by DRAW_BUFFERi + // The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not + // be NONE for any color attachment point(s) named by + // DRAW_BUFFERi. glGenFramebuffersEXT(1, fbs); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + @@ -1285,13 +1295,13 @@ FBOTest::testErrorHandling(void) glDeleteFramebuffersEXT(1, fbs); if (status != GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT) { REPORT_FAILURE - ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"); + ("All any buffer named by glDrawBuffers is missing, status should be GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"); return false; } // If READ_BUFFER is not NONE, then the value of - // FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be NONE for the - // color attachment point named by READ_BUFFER. + // FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be NONE for + // the color attachment point named by READ_BUFFER. glGenFramebuffersEXT(1, fbs); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); glDrawBuffer(GL_NONE); @@ -1302,7 +1312,7 @@ FBOTest::testErrorHandling(void) glDeleteFramebuffersEXT(1, fbs); if (status != GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT) { REPORT_FAILURE - ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"); + ("If buffer named by glReadBuffers is missing, status should be GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"); return false; } } diff --git a/tests/glean/tfbo.h b/tests/glean/tfbo.h index 4a35c6024..01d0d271c 100644 --- a/tests/glean/tfbo.h +++ b/tests/glean/tfbo.h @@ -57,6 +57,7 @@ private: typedef bool (FBOTest::*TestFunc)(MultiTestResult &r); typedef bool (FBOTest::*SubTestFunc)(void); + GLboolean haveARBfbo; // GL_ARB_framebuffer_object supported? GLfloat tolerance[5]; void reset(void); bool testFunctionality(MultiTestResult &r); diff --git a/tests/glean/tfpexceptions.cpp b/tests/glean/tfpexceptions.cpp index 7a93eda1e..2038007a7 100644 --- a/tests/glean/tfpexceptions.cpp +++ b/tests/glean/tfpexceptions.cpp @@ -480,7 +480,7 @@ FPExceptionsTest::testOverflow(void) GLdouble mat[16]; for (int i = 0; i < 15; i++) mat[i] = 0.0; - mat[0] = mat[5] = mat[10] = mat[15] = 1.0e500; + mat[0] = mat[5] = mat[10] = mat[15] = 1.0e100; glMatrixMode(GL_MODELVIEW); glPushMatrix(); diff --git a/tests/glean/tfragprog1.cpp b/tests/glean/tfragprog1.cpp index 99e051a81..9abe354c8 100644 --- a/tests/glean/tfragprog1.cpp +++ b/tests/glean/tfragprog1.cpp @@ -39,10 +39,11 @@ // unique programs work correctly. -#include "tfragprog1.h" +#include <cstring> #include <cassert> #include <cmath> #include <math.h> +#include "tfragprog1.h" namespace GLEAN { @@ -436,6 +437,17 @@ static const FragmentProgram Programs[] = { DONT_CARE_Z }, { + /* check that RCP result is replicated across XYZW */ + "RCP test 2 (reciprocal)", + "!!ARBfp1.0\n" + "PARAM values = {8, -10, 1, 12 }; \n" + "MOV result.color, values; \n" + "RCP result.color, values.x; \n" + "END \n", + { 1.0 / 8.0, 1.0 / 8.0, 1.0 / 8.0, 1.0 / 8.0 }, + DONT_CARE_Z + }, + { "RSQ test 1 (reciprocal square root)", "!!ARBfp1.0\n" "PARAM values = {1, 4, 9, 100 }; \n" @@ -563,6 +575,18 @@ static const FragmentProgram Programs[] = { DONT_CARE_Z }, { + "swizzled move test", + "!!ARBfp1.0\n" + "TEMP t; \n" + "PARAM p = program.local[1]; \n" + "MOV t, p; \n" + "MOV t, t.yxwz; \n" // "in-place" swizzle + "MOV result.color, t; \n" + "END \n", + { Param1[1], Param1[0], Param1[3], Param1[2] }, + DONT_CARE_Z + }, + { "XPD test 1", "!!ARBfp1.0\n" "PARAM p1 = program.local[1]; \n" diff --git a/tests/glean/tglsl1.cpp b/tests/glean/tglsl1.cpp index 469485f94..42bc9c4ed 100644 --- a/tests/glean/tglsl1.cpp +++ b/tests/glean/tglsl1.cpp @@ -1,6 +1,7 @@ // BEGIN_COPYRIGHT -*- glean -*- // // Copyright (C) 1999 Allen Akin All Rights Reserved. +// Copyright (C) 2008 VMWare, Inc. All Rights Reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -31,9 +32,11 @@ #define GL_GLEXT_PROTOTYPES -#include "tglsl1.h" +#include <stdlib.h> #include <cassert> +#include <cstring> #include <math.h> +#include "tglsl1.h" namespace GLEAN { @@ -81,7 +84,7 @@ static PFNGLUNIFORMMATRIX4X3FVPROC glUniformMatrix4x3fv_func = NULL; #define FLAG_LOOSE 0x1 // to indicate a looser tolerance test is needed #define FLAG_ILLEGAL_SHADER 0x2 // the shader test should not compile #define FLAG_ILLEGAL_LINK 0x4 // the shaders should not link -#define FLAG_VERSION_2_1 0x8 // OpenGL 2.1 test (or GLSL 1.20) +#define FLAG_VERSION_1_20 0x8 // GLSL 1.20 test #define FLAG_WINDING_CW 0x10 // clockwise-winding polygon #define FLAG_VERTEX_TEXTURE 0x20 @@ -333,6 +336,47 @@ static const ShaderProgram Programs[] = { FLAG_NONE }, + { + "Swizzled expression", + NO_VERTEX_SHADER, + "void main() { \n" + " vec4 a = vec4(1, 1, 1, 1); \n" + " vec4 b = vec4(0.5, 0.2, 0.1, 0.8); \n" + " vec4 c = (a * b).wzyx; \n" + " gl_FragColor = c; \n" + "} \n", + { 0.8, 0.1, 0.2, 0.5 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { + "Swizzled swizzle", + NO_VERTEX_SHADER, + "void main() { \n" + " vec4 a = vec4(0.1, 0.2, 0.3, 0.4); \n" + " vec4 b = a.wzyx.yxwz; \n" + " gl_FragColor = b; \n" + "} \n", + { 0.3, 0.4, 0.1, 0.2 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { + "Swizzled swizzled swizzle", + NO_VERTEX_SHADER, + "void main() { \n" + " vec4 a = vec4(0.1, 0.2, 0.3, 0.4); \n" + " vec4 b = a.wzyx.yxwz.xxyz; \n" + " gl_FragColor = b; \n" + "} \n", + { 0.3, 0.3, 0.4, 0.1 }, + DONT_CARE_Z, + FLAG_NONE + }, + + // Z-write ============================================================ { "gl_FragDepth writing", @@ -1057,6 +1101,19 @@ static const ShaderProgram Programs[] = { }, { + "conditional expression (2)", + NO_VERTEX_SHADER, + "void main() { \n" + " gl_FragColor = vec4(0.0); \n" + " bool b = true; \n" + " gl_FragColor.y = b ? 1.0 : 0.5; \n" + "} \n", + { 0.0, 1.0, 0.0, 0.0 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { "sequence (comma) operator", NO_VERTEX_SHADER, "void main() { \n" @@ -1088,6 +1145,45 @@ static const ShaderProgram Programs[] = { FLAG_NONE }, + { + "array with variable indexing", + NO_VERTEX_SHADER, + "uniform vec4 uniform1; \n" + "void main() { \n" + " float ar[4]; \n" + " ar[0] = 0.0; \n" + " ar[1] = 0.1; \n" + " ar[2] = 0.5; \n" + " ar[3] = 0.7; \n" + " int indx = int(uniform1.y * 8.0); // should be 2 \n" + " gl_FragColor = vec4(ar[indx]); \n" + "} \n", + { 0.5, 0.5, 0.5, 0.5 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { + "array with swizzled variable indexing", + NO_VERTEX_SHADER, + "uniform vec4 uniform1; \n" + "void main() { \n" + " float ar[4]; \n" + " ar[0] = 0.0; \n" + " ar[1] = 0.8; \n" + " ar[2] = 0.5; \n" + " ar[3] = 0.7; \n" + " ivec2 indx; \n" + " indx.x = 1; \n" + " indx.y = int(uniform1.y * 8.0); // should be 2 \n" + " float p = ar[indx.x] * ar[indx.y]; \n" + " gl_FragColor = vec4(p); \n" + "} \n", + { 0.4, 0.4, 0.4, 0.4 }, + DONT_CARE_Z, + FLAG_NONE + }, + #if 0 // XXX enable someday { "vector subscript *=", @@ -2069,7 +2165,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " vec4 a = vec4( 1.0, 0.0, 0.2, 0.5); \n" " vec4 b = vec4( 1.0, 3.0, 0.0, 0.5); \n" - " gl_FragColor = equal(a, b); \n" + " gl_FragColor = vec4(equal(a, b)); \n" "} \n", { 1.0, 0.0, 0.0, 1.0 }, DONT_CARE_Z, @@ -2082,7 +2178,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " vec4 a = vec4( 1.0, 0.0, 0.2, 0.5); \n" " vec4 b = vec4( 1.0, 3.0, 0.0, 0.5); \n" - " gl_FragColor = notEqual(a, b); \n" + " gl_FragColor = vec4(notEqual(a, b)); \n" "} \n", { 0.0, 1.0, 1.0, 0.0 }, DONT_CARE_Z, @@ -2095,7 +2191,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " vec4 a = vec4( 0.5, 1.0, 0.4, 0.0); \n" " vec4 b = vec4( 1.0, 0.2, 0.4, 0.0); \n" - " gl_FragColor = lessThanEqual(a, b); \n" + " gl_FragColor = vec4(lessThanEqual(a, b)); \n" "} \n", { 1.0, 0.0, 1.0, 1.0 }, DONT_CARE_Z, @@ -2108,7 +2204,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " vec4 a = vec4( 0.5, 1.0, 0.4, 0.0); \n" " vec4 b = vec4( 1.0, 0.2, 0.4, 0.0); \n" - " gl_FragColor = greaterThanEqual(a, b); \n" + " gl_FragColor = vec4(greaterThanEqual(a, b)); \n" "} \n", { 0.0, 1.0, 1.0, 1.0 }, DONT_CARE_Z, @@ -2121,7 +2217,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " vec4 a = vec4( 0.5, 1.0, 0.4, 0.0); \n" " vec4 b = vec4( 1.0, 0.2, 0.4, 0.0); \n" - " gl_FragColor = lessThan(a, b); \n" + " gl_FragColor = vec4(lessThan(a, b)); \n" "} \n", { 1.0, 0.0, 0.0, 0.0 }, DONT_CARE_Z, @@ -2134,7 +2230,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " vec4 a = vec4( 0.5, 1.0, 0.4, 0.0); \n" " vec4 b = vec4( 1.0, 0.2, 0.4, 0.0); \n" - " gl_FragColor = greaterThan(a, b); \n" + " gl_FragColor = vec4(greaterThan(a, b)); \n" "} \n", { 0.0, 1.0, 0.0, 0.0 }, DONT_CARE_Z, @@ -2234,6 +2330,93 @@ static const ShaderProgram Programs[] = { FLAG_NONE }, + { + "struct (1)", + NO_VERTEX_SHADER, + "struct s1 { \n" + " float f1; \n" + " vec4 v4; \n" + "}; \n" + "\n" + "void main() { \n" + " s1 a, b; \n" + " a.v4 = vec4(0.25, 0.5, 0.75, 1.0); \n" + " a.f1 = 0.0; \n" + " b = a; \n" + " gl_FragColor = b.v4; \n" + "} \n", + { 0.25, 0.5, 0.75, 1.0 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { + "struct (2)", + NO_VERTEX_SHADER, + "struct s1 { \n" + " float f1; \n" + " vec4 v4; \n" + "}; \n" + "\n" + "void main() { \n" + " s1 a[2]; \n" + " a[0].v4 = vec4(0.25, 0.5, 0.75, 1.0); \n" + " a[0].f1 = 0.0; \n" + " a[1] = a[0]; \n" + " gl_FragColor = a[1].v4; \n" + "} \n", + { 0.25, 0.5, 0.75, 1.0 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { + "struct (3)", + NO_VERTEX_SHADER, + "struct s1 { \n" + " float f1; \n" + " vec4 v4; \n" + "}; \n" + "\n" + "void main() { \n" + " vec4 scale = vec4(0.5); \n" + " vec4 bias = vec4(0.1); \n" + " s1 a; \n" + " a.v4 = vec4(0.25, 0.5, 0.75, 1.0); \n" + " a.f1 = 0.0; \n" + " gl_FragColor = a.v4 * scale + bias; \n" + "} \n", + { 0.225, 0.35, 0.475, 0.6 }, + DONT_CARE_Z, + FLAG_NONE + }, + + { + "struct (4)", + NO_VERTEX_SHADER, + "struct s1 { \n" + " float foo; \n" + " vec4 v4; \n" + "}; \n" + "struct s2 { \n" + " float bar; \n" + " s1 s; \n" + " float baz; \n" + "}; \n" + "\n" + "void main() { \n" + " s2 a; \n" + " a.s.v4 = vec4(0.25, 0.5, 0.75, 1.0); \n" + " a.bar = 0.0; \n" + " a.baz = 0.0; \n" + " a.s.foo = 0.0; \n" + " gl_FragColor = a.s.v4; \n" + "} \n", + { 0.25, 0.5, 0.75, 1.0 }, + DONT_CARE_Z, + FLAG_NONE + }, + // Preprocessor tests ================================================ { "Preprocessor test (1)", @@ -2391,7 +2574,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.5, 0.6, 0.7, 0.8 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "mat4x2 construct", @@ -2407,7 +2590,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.3, 0.4, 0.5, 0.6 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "mat2x3 construct", @@ -2421,7 +2604,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.4, 0.5, 0.6, 1.0 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "mat3x2 construct", @@ -2436,7 +2619,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.3, 0.4, 0.5, 0.6 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "mat4x3 construct", @@ -2452,7 +2635,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.4, 0.5, 0.6, 1.0 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "mat3x4 construct", @@ -2466,7 +2649,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.5, 0.6, 0.7, 0.8 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { @@ -2486,7 +2669,7 @@ static const ShaderProgram Programs[] = { 0.2 * 0.9 + -0.2 * 1.0 + 0.4 * 0.0 + 0.1 * 1.0, 1.0 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { @@ -2508,7 +2691,7 @@ static const ShaderProgram Programs[] = { 0.0 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { @@ -2534,7 +2717,7 @@ static const ShaderProgram Programs[] = { (0.2 * 0.5 + 0.4 * 0.4 + 0.6 * 0.3 + 0.8 * 0.2) * 0.5 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { @@ -2554,7 +2737,7 @@ static const ShaderProgram Programs[] = { 0.2 * 0.5 + 0.5 * 0.6, 0.2 * 0.7 + 0.5 * 0.8 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "vec3 * mat4x3 multiply", @@ -2573,7 +2756,7 @@ static const ShaderProgram Programs[] = { 0.2 * 0.7 + 0.5 * 0.8 + 0.1 * 0.9, 0.2 * 1.0 + 0.5 * 0.1 + 0.1 * 0.2 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { @@ -2586,7 +2769,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.0, 0.1, 0.2, 0.3 }, // first column of 2x4 matrix DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "uniform matrix 2x4, transposed", @@ -2598,7 +2781,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.0, 0.2, 0.4, 0.6 }, // first row of 4x2 matrix DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "uniform matrix 4x3", @@ -2611,7 +2794,7 @@ static const ShaderProgram Programs[] = { "} \n", { 0.3, 0.4, 0.5, 1.0 }, // second column of 4x3 matrix DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, { "uniform matrix 4x3, transposed", @@ -2624,10 +2807,161 @@ static const ShaderProgram Programs[] = { "} \n", { 0.1, 0.5, 0.9, 1.0 }, DONT_CARE_Z, - FLAG_VERSION_2_1 + FLAG_VERSION_1_20 }, - // Illegal link test =================================================== + // Tests for GLSL 1.20 new array features + { + "GLSL 1.20 arrays", + NO_VERTEX_SHADER, + "#version 120 \n" + "float [2] x; \n" + "void main() { \n" + " x[0] = 1.0; \n" + " x[1] = 2.0; \n" + " gl_FragColor.x = x[0]; \n" + " gl_FragColor.y = 0.25 * x[1]; \n" + " gl_FragColor.z = 0.1 * (x[0] + x[1]); \n" + " gl_FragColor.w = 1.0; \n" + "} \n", + { 1.0, 0.5, 0.3, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 array constructor 1", + NO_VERTEX_SHADER, + "#version 120 \n" + "float [2] x = float[2](1.0, 2.0); \n" + "void main() { \n" + " gl_FragColor.x = x[0]; \n" + " gl_FragColor.y = 0.25 * x[1]; \n" + " gl_FragColor.z = 0.1 * (x[0] + x[1]); \n" + " gl_FragColor.w = 1.0; \n" + "} \n", + { 1.0, 0.5, 0.3, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 array constructor 2", + NO_VERTEX_SHADER, + "#version 120 \n" + "vec4 [2] colors = vec4[2](vec4(0.5, 0.4, 0.3, 0.2), \n" + " vec4(0.7, 0.8, 0.9, 1.0)); \n" + "void main() { \n" + " gl_FragColor = colors[1]; \n" + "} \n", + { 0.7, 0.8, 0.9, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 const array constructor 1", + NO_VERTEX_SHADER, + "#version 120 \n" + "const float [2] x = float[2](1.0, 2.0); \n" + "void main() { \n" + " gl_FragColor.x = x[0]; \n" + " gl_FragColor.y = 0.25 * x[1]; \n" + " gl_FragColor.z = 0.1 * (x[0] + x[1]); \n" + " gl_FragColor.w = 1.0; \n" + "} \n", + { 1.0, 0.5, 0.3, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 const array constructor 2", + NO_VERTEX_SHADER, + "#version 120 \n" + "const vec4 [2] colors = vec4[2](vec4(0.5, 0.4, 0.3, 0.2), \n" + " vec4(0.7, 0.8, 0.9, 1.0)); \n" + "void main() { \n" + " gl_FragColor = colors[1]; \n" + "} \n", + { 0.7, 0.8, 0.9, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 uniform array constructor", + NO_VERTEX_SHADER, + "#version 120 \n" + "uniform float [2] x = float[2](1.0, 2.0); \n" + "void main() { \n" + " gl_FragColor.x = x[0]; \n" + " gl_FragColor.y = 0.25 * x[1]; \n" + " gl_FragColor.z = 0.1 * (x[0] + x[1]); \n" + " gl_FragColor.w = 1.0; \n" + "} \n", + { 1.0, 0.5, 0.3, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 array.length()", + NO_VERTEX_SHADER, + "#version 120 \n" + "const float [2] x = float[2](1.0, 2.0); \n" + "void main() { \n" + " int l = x.length(); \n" + " gl_FragColor = vec4(l * 0.25); \n" + "} \n", + { 0.5, 0.5, 0.5, 0.5 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 array error check", + NO_VERTEX_SHADER, + "#version 120 \n" + "// Note array size disagreement here: \n" + "const float [2] x = float[3](1.0, 2.0); \n" + "void main() { \n" + " gl_FragColor = vec4(1); \n" + "} \n", + { 1.0, 1.0, 1.0, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 | FLAG_ILLEGAL_SHADER + }, + + // Other new GLSL 1.20 features (just parse/compile tests) + { + "GLSL 1.20 precision qualifiers", + NO_VERTEX_SHADER, + "#version 120 \n" + "highp float f1; \n" + "mediump float f2; \n" + "lowp float f3; \n" + "precision mediump float; \n" + "precision lowp int; \n" + "precision highp float; \n" + "void main() { \n" + " gl_FragColor = vec4(1); \n" + "} \n", + { 1.0, 1.0, 1.0, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + { + "GLSL 1.20 invariant, centroid qualifiers", + NO_VERTEX_SHADER, + "#version 120 \n" + "invariant varying vec4 v1; \n" + "centroid varying vec4 v2; \n" + "invariant centroid varying vec4 v3; \n" + "varying vec4 v4; \n" + "invariant v4; \n" + "void main() { \n" + " gl_FragColor = vec4(1); \n" + "} \n", + { 1.0, 1.0, 1.0, 1.0 }, + DONT_CARE_Z, + FLAG_VERSION_1_20 + }, + + // Illegal link test ================================================== { "gl_Position not written check", "void main() { \n" @@ -2657,6 +2991,42 @@ static const ShaderProgram Programs[] = { FLAG_ILLEGAL_LINK }, + { + "varying read but not written", + // vert shader: + "varying vec4 foo; \n" + "void main() { \n" + " gl_Position = ftransform(); \n" + "} \n", + // frag shader: + "varying vec4 foo; \n" + "void main() { \n" + " gl_FragColor = foo; \n" + "} \n", + { 0.0, 0.0, 0.0, 0.0 }, + DONT_CARE_Z, + FLAG_ILLEGAL_LINK + }, + + { + "texcoord varying", + // Does the linker correctly recognize that texcoord[1] is + // written by the vertex shader and read by the fragment shader? + // vert shader: + "void main() { \n" + " int i = 1; \n" + " gl_TexCoord[i] = vec4(0.5, 0, 0, 0); \n" + " gl_Position = ftransform(); \n" + "} \n", + // frag shader: + "void main() { \n" + " gl_FragColor = gl_TexCoord[1]; \n" + "} \n", + { 0.5, 0.0, 0.0, 0.0 }, + DONT_CARE_Z, + FLAG_NONE + }, + { NULL, NULL, NULL, {0,0,0,0}, 0, FLAG_NONE } // end of list sentinal }; @@ -2964,16 +3334,17 @@ GLSLTest::setupTextureMatrix1(void) bool GLSLTest::setup(void) { - // check that we have OpenGL 2.0 - const char *verString = (const char *) glGetString(GL_VERSION); - if (verString[0] != '2' || verString[1] != '.') { - //env->log << "OpenGL 2.x not supported\n"; + // check GLSL version +#ifdef GL_SHADING_LANGUAGE_VERSION + const char *glslVersion = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION); +#else + const char *glslVersion = NULL; +#endif + if (!glslVersion || glslVersion[0] != '1') { + env->log << "GLSL 1.x not supported\n"; return false; } - if (verString[2] >= '1') - version21 = GL_TRUE; // update when needed - else - version21 = GL_FALSE; // play it safe + glsl_120 = (glslVersion[2] >= '2'); if (!getFunctions()) { env->log << "Unable to get pointer to an OpenGL 2.0 API function\n"; @@ -3399,7 +3770,7 @@ GLSLTest::runOne(MultiTestResult &r, Window &w) else { // loop over all tests for (int i = 0; Programs[i].name; i++) { - if ((Programs[i].flags & FLAG_VERSION_2_1) && !version21) + if ((Programs[i].flags & FLAG_VERSION_1_20) && !glsl_120) continue; // skip non-applicable tests if (testProgram(Programs[i])) { r.numPassed++; @@ -3413,9 +3784,27 @@ GLSLTest::runOne(MultiTestResult &r, Window &w) } +// We need OpenGL 2.0, 2.1 or 3.0 +bool +GLSLTest::isApplicable() const +{ + const char *version = (const char *) glGetString(GL_VERSION); + if (strncmp(version, "2.0", 3) == 0 || + strncmp(version, "2.1", 3) == 0 || + strncmp(version, "3.0", 3) == 0) { + return true; + } + else { + env->log << name + << ": skipped. Requires GL 2.0, 2.1 or 3.0.\n"; + return false; + } +} + + // The test object itself: GLSLTest glslTest("glsl1", "window, rgb, z", - "", // no extension filter (we'll test for version 2.x during setup) + "", // no extension filter but see isApplicable() "GLSL test 1: test basic Shading Language functionality.\n" ); diff --git a/tests/glean/tglsl1.h b/tests/glean/tglsl1.h index 84a3d723f..73972b0e9 100644 --- a/tests/glean/tglsl1.h +++ b/tests/glean/tglsl1.h @@ -59,14 +59,17 @@ public: const char *extensions, const char* description): MultiTest(testName, filter, extensions, description) { + testOne = true; // test with just one surface config } + bool isApplicable() const; + virtual void runOne(MultiTestResult &r, Window &w); private: GLfloat tolerance[5]; GLfloat looseTolerance[5]; - GLfloat version21; // OpenGL 2.1 or higher supported? + GLfloat glsl_120; // GLSL 1.20 or higher supported? bool getFunctions(void); void setupTextures(void); void setupTextureMatrix1(void); diff --git a/tests/glean/tlogicop.cpp b/tests/glean/tlogicop.cpp index 06a80cfce..470654a7a 100644 --- a/tests/glean/tlogicop.cpp +++ b/tests/glean/tlogicop.cpp @@ -30,10 +30,11 @@ // Based on Allen's blendFunc test. // Brian Paul 10 May 2001 +#include <stdlib.h> +#include <cmath> #include "tlogicop.h" #include "rand.h" #include "image.h" -#include <cmath> namespace { diff --git a/tests/glean/toccluqry.cpp b/tests/glean/toccluqry.cpp index 7cc49b445..a362fc130 100644 --- a/tests/glean/toccluqry.cpp +++ b/tests/glean/toccluqry.cpp @@ -33,10 +33,12 @@ */ #define GL_GLEXT_PROTOTYPES -#include "toccluqry.h" +#include <stdlib.h> #include <cassert> +#include <cstring> #include <stdio.h> #include <cmath> +#include "toccluqry.h" #define START_QUERY(id)\ @@ -84,7 +86,7 @@ GLuint OccluQryTest::find_unused_id() while (1) { /* assuming that at least 2^32-1 <id> can be generated */ - id = random() % ((unsigned long)1 << 32 - 1); + id = random() % (((unsigned long) 1 << 32) - 1); if (id != 0 && glIsQueryARB(id) == GL_FALSE) return id; if (++ counter >= MAX_FIND_ID_ROUND) { diff --git a/tests/glean/tpaths.cpp b/tests/glean/tpaths.cpp index 00926ea11..eed2194e6 100644 --- a/tests/glean/tpaths.cpp +++ b/tests/glean/tpaths.cpp @@ -41,6 +41,7 @@ // // Author: Brian Paul (brianp@valinux.com) November 2000 +#include <stdlib.h> #include "tpaths.h" namespace GLEAN { diff --git a/tests/glean/tpbo.cpp b/tests/glean/tpbo.cpp index 4642690df..5ae7a5745 100644 --- a/tests/glean/tpbo.cpp +++ b/tests/glean/tpbo.cpp @@ -34,10 +34,15 @@ #define GL_GLEXT_PROTOTYPES
-#include "tpbo.h"
+
+#include <stdlib.h>
+#include <cstring>
#include <cassert>
#include <math.h>
+#include "tpbo.h"
#include "timer.h"
+
+
namespace GLEAN
{
@@ -79,12 +84,12 @@ bool PBOTest::setup(void) // Check if GL_ARB_pixel_buffer_object is supported
if (!strstr((char *) glGetString(GL_EXTENSIONS), "GL_ARB_pixel_buffer_object")) {
- printf("GL_ARB_pixel_buffer_object is not supported\n");
+ //printf("GL_ARB_pixel_buffer_object is not supported\n");
usePBO = 0;
return false;
}
else {
- printf("GL_ARB_pixel_buffer_object is supported\n");
+ //printf("GL_ARB_pixel_buffer_object is supported\n");
usePBO = 1;
}
diff --git a/tests/glean/tpixelformats.cpp b/tests/glean/tpixelformats.cpp index 867ba08fa..3603bf571 100644 --- a/tests/glean/tpixelformats.cpp +++ b/tests/glean/tpixelformats.cpp @@ -27,9 +27,10 @@ // END_COPYRIGHT -#include "tpixelformats.h" +#include <stdlib.h> #include <cassert> #include <cmath> +#include "tpixelformats.h" // Set to 1 to help debug test failures: diff --git a/tests/glean/tpointsprite.cpp b/tests/glean/tpointsprite.cpp index 47cff89ae..280984c29 100644 --- a/tests/glean/tpointsprite.cpp +++ b/tests/glean/tpointsprite.cpp @@ -40,10 +40,13 @@ */ #define GL_GLEXT_PROTOTYPES -#include "tpointsprite.h" + +#include <stdlib.h> #include <cassert> #include <cmath> #include <stdio.h> +#include "tpointsprite.h" + namespace GLEAN { diff --git a/tests/glean/tshaderapi.cpp b/tests/glean/tshaderapi.cpp new file mode 100644 index 000000000..643bb6214 --- /dev/null +++ b/tests/glean/tshaderapi.cpp @@ -0,0 +1,600 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +// Test GLSL-related API functions for correct behaviour +// Based on the "shader_api.c" test from Mesa, written by Bruce Merry. + + +#include <cstring> +#include "tshaderapi.h" +#include "rand.h" +#include "timer.h" +#include "image.h" + + +namespace GLEAN { + +static PFNGLATTACHSHADERPROC glAttachShader_func = NULL; +static PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation_func = NULL; +static PFNGLCOMPILESHADERPROC glCompileShader_func = NULL; +static PFNGLCREATEPROGRAMPROC glCreateProgram_func = NULL; +static PFNGLCREATESHADERPROC glCreateShader_func = NULL; +static PFNGLDELETEPROGRAMPROC glDeleteProgram_func = NULL; +static PFNGLDELETESHADERPROC glDeleteShader_func = NULL; +static PFNGLDETACHSHADERPROC glDetachShader_func = NULL; +static PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray_func = NULL; +static PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray_func = NULL; +static PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib_func = NULL; +static PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform_func = NULL; +static PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders_func = NULL; +static PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation_func = NULL; +static PFNGLGETPROGRAMIVPROC glGetProgramiv_func = NULL; +static PFNGLGETPROGRAMINFOLOGPROC glGetPrograminfolog_func = NULL; +static PFNGLGETSHADERIVPROC glGetShaderiv_func = NULL; +static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_func = NULL; +static PFNGLGETSHADERSOURCEPROC glGetShaderSource_func = NULL; +static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_func = NULL; +static PFNGLGETUNIFORMFVPROC glGetUniformfv_func = NULL; +static PFNGLGETUNIFORMIVPROC glGetUniformiv_func = NULL; +static PFNGLLINKPROGRAMPROC glLinkProgram_func = NULL; +static PFNGLSHADERSOURCEPROC glShaderSource_func = NULL; +static PFNGLUSEPROGRAMPROC glUseProgram_func = NULL; +static PFNGLUNIFORM1FPROC glUniform1f_func = NULL; +static PFNGLUNIFORM2FPROC glUniform2f_func = NULL; +static PFNGLUNIFORM3FPROC glUniform3f_func = NULL; +static PFNGLUNIFORM4FPROC glUniform4f_func = NULL; +static PFNGLUNIFORM1IPROC glUniform1i_func = NULL; +static PFNGLUNIFORM2IPROC glUniform2i_func = NULL; +static PFNGLUNIFORM3IPROC glUniform3i_func = NULL; +static PFNGLUNIFORM4IPROC glUniform4i_func = NULL; +static PFNGLUNIFORM1FVPROC glUniform1fv_func = NULL; +static PFNGLUNIFORM2FVPROC glUniform2fv_func = NULL; +static PFNGLUNIFORM3FVPROC glUniform3fv_func = NULL; +static PFNGLUNIFORM4FVPROC glUniform4fv_func = NULL; +static PFNGLUNIFORM1IVPROC glUniform1iv_func = NULL; +static PFNGLUNIFORM2IVPROC glUniform2iv_func = NULL; +static PFNGLUNIFORM3IVPROC glUniform3iv_func = NULL; +static PFNGLUNIFORM4IVPROC glUniform4iv_func = NULL; +static PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv_func = NULL; +static PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv_func = NULL; +static PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv_func = NULL; +static PFNGLVALIDATEPROGRAMPROC glValidateProgram_func = NULL; + + +ShaderAPIResult::ShaderAPIResult() +{ + pass = false; +} + + +void +ShaderAPITest::get_ext_procs(void) +{ + glAttachShader_func = (PFNGLATTACHSHADERPROC) GLUtils::getProcAddress("glAttachShader"); + glBindAttribLocation_func = (PFNGLBINDATTRIBLOCATIONPROC) GLUtils::getProcAddress("glBindAttribLocation"); + glCompileShader_func = (PFNGLCOMPILESHADERPROC) GLUtils::getProcAddress("glCompileShader"); + glCreateProgram_func = (PFNGLCREATEPROGRAMPROC) GLUtils::getProcAddress("glCreateProgram"); + glCreateShader_func = (PFNGLCREATESHADERPROC) GLUtils::getProcAddress("glCreateShader"); + glDeleteProgram_func = (PFNGLDELETEPROGRAMPROC) GLUtils::getProcAddress("glDeleteProgram"); + glDeleteShader_func = (PFNGLDELETESHADERPROC) GLUtils::getProcAddress("glDeleteShader"); + glDetachShader_func = (PFNGLDETACHSHADERPROC) GLUtils::getProcAddress("glDetachShader"); + glDisableVertexAttribArray_func = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) GLUtils::getProcAddress("glDisableVertexAttribArray"); + glEnableVertexAttribArray_func = (PFNGLENABLEVERTEXATTRIBARRAYPROC) GLUtils::getProcAddress("glEnableVertexAttribArray"); + glGetActiveAttrib_func = (PFNGLGETACTIVEATTRIBPROC) GLUtils::getProcAddress("glGetActiveAttrib"); + glGetActiveUniform_func = (PFNGLGETACTIVEUNIFORMPROC) GLUtils::getProcAddress("glGetActiveUniform"); + glGetAttachedShaders_func = (PFNGLGETATTACHEDSHADERSPROC) GLUtils::getProcAddress("glGetAttachedShaders"); + glGetAttribLocation_func = (PFNGLGETATTRIBLOCATIONPROC) GLUtils::getProcAddress("glGetAttribLocation"); + glGetProgramiv_func = (PFNGLGETPROGRAMIVPROC) GLUtils::getProcAddress("glGetProgramiv"); + glGetPrograminfolog_func = (PFNGLGETPROGRAMINFOLOGPROC) GLUtils::getProcAddress("glGetPrograminfolog"); + glGetShaderiv_func = (PFNGLGETSHADERIVPROC) GLUtils::getProcAddress("glGetShaderiv"); + glGetShaderInfoLog_func = (PFNGLGETSHADERINFOLOGPROC) GLUtils::getProcAddress("glGetShaderInfoLog"); + glGetShaderSource_func = (PFNGLGETSHADERSOURCEPROC) GLUtils::getProcAddress("glGetShaderSource"); + glGetUniformLocation_func = (PFNGLGETUNIFORMLOCATIONPROC) GLUtils::getProcAddress("glGetUniformLocation"); + glGetUniformfv_func = (PFNGLGETUNIFORMFVPROC) GLUtils::getProcAddress("glGetUniformfv"); + glGetUniformiv_func = (PFNGLGETUNIFORMIVPROC) GLUtils::getProcAddress("glGetUniformiv"); + glLinkProgram_func = (PFNGLLINKPROGRAMPROC) GLUtils::getProcAddress("glLinkProgram"); + glShaderSource_func = (PFNGLSHADERSOURCEPROC) GLUtils::getProcAddress("glShaderSource"); + glUseProgram_func = (PFNGLUSEPROGRAMPROC) GLUtils::getProcAddress("glUseProgram"); + glUniform1f_func = (PFNGLUNIFORM1FPROC) GLUtils::getProcAddress("glUniform1f"); + glUniform2f_func = (PFNGLUNIFORM2FPROC) GLUtils::getProcAddress("glUniform2f"); + glUniform3f_func = (PFNGLUNIFORM3FPROC) GLUtils::getProcAddress("glUniform3f"); + glUniform4f_func = (PFNGLUNIFORM4FPROC) GLUtils::getProcAddress("glUniform4f"); + glUniform1i_func = (PFNGLUNIFORM1IPROC) GLUtils::getProcAddress("glUniform1i"); + glUniform2i_func = (PFNGLUNIFORM2IPROC) GLUtils::getProcAddress("glUniform2i"); + glUniform3i_func = (PFNGLUNIFORM3IPROC) GLUtils::getProcAddress("glUniform3i"); + glUniform4i_func = (PFNGLUNIFORM4IPROC) GLUtils::getProcAddress("glUniform4i"); + glUniform1fv_func = (PFNGLUNIFORM1FVPROC) GLUtils::getProcAddress("glUniform1fv"); + glUniform2fv_func = (PFNGLUNIFORM2FVPROC) GLUtils::getProcAddress("glUniform2fv"); + glUniform3fv_func = (PFNGLUNIFORM3FVPROC) GLUtils::getProcAddress("glUniform3fv"); + glUniform4fv_func = (PFNGLUNIFORM4FVPROC) GLUtils::getProcAddress("glUniform4fv"); + glUniform1iv_func = (PFNGLUNIFORM1IVPROC) GLUtils::getProcAddress("glUniform1iv"); + glUniform2iv_func = (PFNGLUNIFORM2IVPROC) GLUtils::getProcAddress("glUniform2iv"); + glUniform3iv_func = (PFNGLUNIFORM3IVPROC) GLUtils::getProcAddress("glUniform3iv"); + glUniform4iv_func = (PFNGLUNIFORM4IVPROC) GLUtils::getProcAddress("glUniform4iv"); + glUniformMatrix2fv_func = (PFNGLUNIFORMMATRIX2FVPROC) GLUtils::getProcAddress("glUniformMatrix2fv"); + glUniformMatrix3fv_func = (PFNGLUNIFORMMATRIX3FVPROC) GLUtils::getProcAddress("glUniformMatrix3fv"); + glUniformMatrix4fv_func = (PFNGLUNIFORMMATRIX4FVPROC) GLUtils::getProcAddress("glUniformMatrix4fv"); + glValidateProgram_func = (PFNGLVALIDATEPROGRAMPROC) GLUtils::getProcAddress("glValidateProgram"); +} + + +void +ShaderAPITest::assert_test(const char *file, int line, int cond, const char *msg) +{ + if (!cond) { + error = true; + fprintf(stderr, "%s:%d assertion \"%s\" failed\n", file, line, msg); + } +} + +#undef assert +#define assert(x) assert_test(__FILE__, __LINE__, (x), #x) + + +void +ShaderAPITest::assert_no_error_test(const char *file, int line) +{ + GLenum err; + + err = glGetError(); + if (err != GL_NO_ERROR) { + error = true; + fprintf(stderr, "%s:%d received error %s\n", + file, line, gluErrorString(err)); + } +} + +#define assert_no_error() assert_no_error_test(__FILE__, __LINE__) + + +void +ShaderAPITest::assert_error_test(const char *file, int line, GLenum expect) +{ + GLenum err; + + err = glGetError(); + if (err != expect) { + fprintf(stderr, "%s:%d expected %s but received %s\n", + file, line, gluErrorString(expect), gluErrorString(err)); + error = true; + } + + while (glGetError()) + ; /* consume any following errors */ +} + +#define assert_error(err) assert_error_test(__FILE__, __LINE__, (err)) + + +void +ShaderAPITest::check_status(GLuint id, GLenum pname, void (*query)(GLuint, GLenum, GLint *)) +{ + GLint status; + + query(id, pname, &status); + if (!status) { + char info[65536]; + + fprintf(stderr, "Compilation/link failure:\n"); + glGetShaderInfoLog_func(id, sizeof(info), NULL, info); + fprintf(stderr, "%s\n", info); + + error = true; + } +} + + +void +ShaderAPITest::check_compile_status(GLuint id) +{ + check_status(id, GL_COMPILE_STATUS, glGetShaderiv_func); +} + + +void +ShaderAPITest::check_link_status(GLuint id) +{ + check_status(id, GL_LINK_STATUS, glGetProgramiv_func); +} + + +GLuint +ShaderAPITest::make_shader(GLenum type, const char *src) +{ + GLuint id; + + assert_no_error(); + id = glCreateShader_func(type); + glShaderSource_func(id, 1, &src, NULL); + glCompileShader_func(id); + check_compile_status(id); + assert_no_error(); + return id; +} + + +GLuint +ShaderAPITest::make_program(const char *vs_src, const char *fs_src) +{ + GLuint id, vs, fs; + + assert_no_error(); + id = glCreateProgram_func(); + if (vs_src) { + vs = make_shader(GL_VERTEX_SHADER, vs_src); + glAttachShader_func(id, vs); + glDeleteShader_func(vs); + } + if (fs_src) { + fs = make_shader(GL_FRAGMENT_SHADER, fs_src); + glAttachShader_func(id, fs); + glDeleteShader_func(fs); + } + glLinkProgram_func(id); + check_link_status(id); + glUseProgram_func(id); + glDeleteProgram_func(id); + assert_no_error(); + return id; +} + + +void +ShaderAPITest::test_uniform_size_type1(const char *glslType, GLenum glType, const char *el) +{ + char buffer[1024]; + GLuint program; + GLint active, i; + GLenum type; + GLint size; + + //printf(" Running subtest %s\n", glslType); + //fflush(stdout); + sprintf(buffer, "#version 120\nuniform %s m[60];\nvoid main() { gl_Position[0] = m[59]%s; }\n", + glslType, el); + + program = make_program(buffer, NULL); + glGetProgramiv_func(program, GL_ACTIVE_UNIFORMS, &active); + assert_no_error(); + for (i = 0; i < active; i++) { + size = -1; + type = 0; + glGetActiveUniform_func(program, i, sizeof(buffer), NULL, + &size, &type, buffer); + assert_no_error(); + if (strncmp(buffer, "m", 1) == 0) + break; + } + assert(i < active); /* Otherwise the compiler optimised it out */ + assert(type == glType); + assert(size == 60); +} + + +void +ShaderAPITest::test_uniform_size_type(void) +{ + test_uniform_size_type1("float", GL_FLOAT, ""); + test_uniform_size_type1("vec2", GL_FLOAT_VEC2, "[0]"); + test_uniform_size_type1("vec3", GL_FLOAT_VEC3, "[0]"); + test_uniform_size_type1("vec4", GL_FLOAT_VEC4, "[0]"); + + test_uniform_size_type1("bool", GL_BOOL, " ? 1.0 : 0.0"); + test_uniform_size_type1("bvec2", GL_BOOL_VEC2, "[0] ? 1.0 : 0.0"); + test_uniform_size_type1("bvec3", GL_BOOL_VEC3, "[0] ? 1.0 : 0.0"); + test_uniform_size_type1("bvec4", GL_BOOL_VEC4, "[0] ? 1.0 : 0.0"); + + test_uniform_size_type1("int", GL_INT, ""); + test_uniform_size_type1("ivec2", GL_INT_VEC2, "[0]"); + test_uniform_size_type1("ivec3", GL_INT_VEC3, "[0]"); + test_uniform_size_type1("ivec4", GL_INT_VEC4, "[0]"); + + test_uniform_size_type1("mat2", GL_FLOAT_MAT2, "[0][0]"); + test_uniform_size_type1("mat3", GL_FLOAT_MAT3, "[0][0]"); + test_uniform_size_type1("mat4", GL_FLOAT_MAT4, "[0][0]"); + test_uniform_size_type1("mat2x3", GL_FLOAT_MAT2x3, "[0][0]"); + test_uniform_size_type1("mat2x4", GL_FLOAT_MAT2x4, "[0][0]"); + test_uniform_size_type1("mat3x2", GL_FLOAT_MAT3x2, "[0][0]"); + test_uniform_size_type1("mat3x4", GL_FLOAT_MAT3x4, "[0][0]"); + test_uniform_size_type1("mat4x2", GL_FLOAT_MAT4x2, "[0][0]"); + test_uniform_size_type1("mat4x3", GL_FLOAT_MAT4x3, "[0][0]"); +} + + +void +ShaderAPITest::test_attrib_size_type1(const char *glslType, GLenum glType, const char *el) +{ + char buffer[1024]; + GLuint program; + GLint active, i; + GLenum type; + GLint size; + + //printf(" Running subtest %s\n", glslType); + //fflush(stdout); + sprintf(buffer, "#version 120\nattribute %s m;\nvoid main() { gl_Position[0] = m%s; }\n", + glslType, el); + + program = make_program(buffer, NULL); + glGetProgramiv_func(program, GL_ACTIVE_ATTRIBUTES, &active); + assert_no_error(); + for (i = 0; i < active; i++) { + size = -1; + type = -1; + glGetActiveAttrib_func(program, i, sizeof(buffer), NULL, + &size, &type, buffer); + assert_no_error(); + if (strncmp(buffer, "m", 1) == 0) + break; + } + assert(i < active); /* Otherwise the compiler optimised it out */ + assert(type == glType); + assert(size == 1); +} + + +void +ShaderAPITest::test_attrib_size_type(void) +{ + test_attrib_size_type1("float", GL_FLOAT, ""); + test_attrib_size_type1("vec2", GL_FLOAT_VEC2, "[0]"); + test_attrib_size_type1("vec3", GL_FLOAT_VEC3, "[0]"); + test_attrib_size_type1("vec4", GL_FLOAT_VEC4, "[0]"); + test_attrib_size_type1("mat2", GL_FLOAT_MAT2, "[0][0]"); + test_attrib_size_type1("mat3", GL_FLOAT_MAT3, "[0][0]"); + test_attrib_size_type1("mat4", GL_FLOAT_MAT4, "[0][0]"); + test_attrib_size_type1("mat2x3", GL_FLOAT_MAT2x3, "[0][0]"); + test_attrib_size_type1("mat2x4", GL_FLOAT_MAT2x4, "[0][0]"); + test_attrib_size_type1("mat3x2", GL_FLOAT_MAT3x2, "[0][0]"); + test_attrib_size_type1("mat3x4", GL_FLOAT_MAT3x4, "[0][0]"); + test_attrib_size_type1("mat4x2", GL_FLOAT_MAT4x2, "[0][0]"); + test_attrib_size_type1("mat4x3", GL_FLOAT_MAT4x3, "[0][0]"); +} + + +void +ShaderAPITest::test_uniform_array_overflow(void) +{ + GLuint program; + GLint location; + GLfloat data[128]; + + program = make_program("#version 120\nuniform vec2 x[10];\nvoid main() { gl_Position.xy = x[9]; }\n", NULL); + location = glGetUniformLocation_func(program, "x"); + assert_no_error(); + glUniform2fv_func(location, 64, data); + assert_no_error(); +} + + +void +ShaderAPITest::test_uniform_scalar_count(void) +{ + GLuint program; + GLint location; + GLfloat data[128]; + + program = make_program("#version 110\nuniform vec2 x;\nvoid main() { gl_Position.xy = x; }\n", NULL); + location = glGetUniformLocation_func(program, "x"); + assert_no_error(); + glUniform2fv_func(location, 64, data); + assert_error(GL_INVALID_OPERATION); +} + + +void +ShaderAPITest::test_uniform_query_matrix(void) +{ + GLuint program; + GLfloat data[18]; + GLint i, r, c; + GLint location; + + program = make_program("#version 110\nuniform mat3 m[2];\nvoid main() { gl_Position.xyz = m[1][2]; }\n", NULL); + location = glGetUniformLocation_func(program, "m"); + for (i = 0; i < 9; i++) + data[i] = i; + for (i = 9; i < 18; i++) + data[i] = 321.0; + glUniformMatrix3fv_func(location, 1, GL_TRUE, data); + + for (i = 0; i < 18; i++) + data[i] = 123.0; + glGetUniformfv_func(program, location, data); + for (c = 0; c < 3; c++) + for (r = 0; r < 3; r++) + assert(data[c * 3 + r] == r * 3 + c); + for (i = 9; i < 18; i++) + assert(data[i] == 123.0); +} + + +void +ShaderAPITest::test_uniform_neg_location(void) +{ + GLuint program; + GLfloat data[4]; + + program = make_program("#version 110\nvoid main() { gl_Position = vec4(1.0, 1.0, 1.0, 1.0); }\n", NULL); + assert_no_error(); + glUniform1i_func(-1, 1); + assert_no_error(); + glUniform1i_func(-200, 1); + assert_error(GL_INVALID_OPERATION); + glUniformMatrix2fv_func(-1, 1, GL_FALSE, data); + assert_no_error(); + glUniformMatrix2fv_func(-200, 1, GL_FALSE, data); + assert_error(GL_INVALID_OPERATION); +} + + +void +ShaderAPITest::test_uniform_bool_conversion(void) +{ + GLuint program; + GLint location; + GLint value[16]; /* in case glGetUniformiv goes nuts on the stack */ + + assert_no_error(); + program = make_program("uniform bool b;\nvoid main() { gl_Position.x = b ? 1.5 : 0.5; }\n", NULL); + location = glGetUniformLocation_func(program, "b"); + assert(location != -1); + assert_no_error(); + glUniform1i_func(location, 5); + assert_no_error(); + glGetUniformiv_func(program, location, &value[0]); + assert_no_error(); + assert(value[0] == 1); +} + + +void +ShaderAPITest::test_uniform_multiple_samplers(void) +{ + GLuint program; + GLint location; + GLint values[2] = {0, 1}; + + assert_no_error(); + program = make_program(NULL, "uniform sampler2D s[2];\nvoid main() { gl_FragColor = texture2D(s[1], vec2(0.0, 0.0)); }\n"); + location = glGetUniformLocation_func(program, "s[0]"); + assert(location != -1); + assert_no_error(); + glUniform1iv_func(location, 2, values); + assert_no_error(); +} + + +void +ShaderAPITest::run_tests(void) +{ + test_uniform_size_type(); + test_attrib_size_type(); + test_uniform_array_overflow(); + test_uniform_scalar_count(); + test_uniform_query_matrix(); + test_uniform_neg_location(); + test_uniform_bool_conversion(); + test_uniform_multiple_samplers(); +} + + +void +ShaderAPITest::runOne(ShaderAPIResult &r, Window &w) +{ + (void) w; // silence warning + + // error will be set to true if any of the assert functions below fail. + error = false; + + get_ext_procs(); + + run_tests(); + + r.pass = !error; +} + + +void +ShaderAPITest::logOne(ShaderAPIResult &r) +{ + if (r.pass) { + logPassFail(r); + logConcise(r); + } + else { + env->log << name << "FAIL\n"; + } +} + + +void +ShaderAPITest::compareOne(ShaderAPIResult &oldR, + ShaderAPIResult &newR) +{ + comparePassFail(oldR, newR); +} + + +void +ShaderAPIResult::putresults(ostream &s) const +{ + if (pass) { + s << "PASS\n"; + } + else { + s << "FAIL\n"; + } +} + + +bool +ShaderAPIResult::getresults(istream &s) +{ + char result[1000]; + s >> result; + + if (strcmp(result, "FAIL") == 0) { + pass = false; + } + else { + pass = true; + } + return s.good(); +} + + +// We need OpenGL 2.0, 2.1 or 3.0 +bool +ShaderAPITest::isApplicable() const +{ + const char *version = (const char *) glGetString(GL_VERSION); + if (strncmp(version, "2.0", 3) == 0 || + strncmp(version, "2.1", 3) == 0 || + strncmp(version, "3.0", 3) == 0) { + return true; + } + else { + env->log << name + << ": skipped. Requires GL 2.0, 2.1 or 3.0.\n"; + return false; + } +} + + +// The test object itself: +ShaderAPITest shaderAPITest("shaderAPI", "window, rgb", + "", // no extensions, but see isApplicable() + "Test GLSL shader-related API features.\n"); + + + +} // namespace GLEAN + + diff --git a/tests/glean/tshaderapi.h b/tests/glean/tshaderapi.h new file mode 100644 index 000000000..e1fc9c1db --- /dev/null +++ b/tests/glean/tshaderapi.h @@ -0,0 +1,94 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +#ifndef __tshaderapi_h__ +#define __tshaderapi_h__ + +#include "tbase.h" + +namespace GLEAN { + +#define windowSize 100 + + +class ShaderAPIResult: public BaseResult +{ +public: + bool pass; + + ShaderAPIResult(); + + virtual void putresults(ostream& s) const; + virtual bool getresults(istream& s); +}; + + +class ShaderAPITest: public BaseTest<ShaderAPIResult> +{ +public: + // "WHO" = width, height and one config flag + GLEAN_CLASS_WHO(ShaderAPITest, ShaderAPIResult, + windowSize, windowSize, true); + + virtual bool isApplicable() const; + +private: + bool error; + + void assert_test(const char *file, int line, int cond, const char *msg); + void assert_no_error_test(const char *file, int line); + void assert_error_test(const char *file, int line, GLenum expect); + + void check_status(GLuint id, GLenum pname, void (*query)(GLuint, GLenum, GLint *)); + void check_compile_status(GLuint id); + void check_link_status(GLuint id); + + GLuint make_shader(GLenum type, const char *src); + GLuint make_program(const char *vs_src, const char *fs_src); + + void test_uniform_size_type1(const char *glslType, GLenum glType, const char *el); + void test_attrib_size_type1(const char *glslType, GLenum glType, const char *el); + + void test_uniform_size_type(void); + void test_attrib_size_type(void); + void test_uniform_array_overflow(void); + void test_uniform_scalar_count(void); + void test_uniform_query_matrix(void); + void test_uniform_neg_location(void); + void test_uniform_bool_conversion(void); + void test_uniform_multiple_samplers(void); + void run_tests(void); + + void get_ext_procs(void); +}; + +} // namespace GLEAN + +#endif // __tshaderapi_h__ + diff --git a/tests/glean/tstencil2.cpp b/tests/glean/tstencil2.cpp new file mode 100644 index 000000000..d0c783a8f --- /dev/null +++ b/tests/glean/tstencil2.cpp @@ -0,0 +1,785 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +// Test two-sided stencil extensions +// Brian Paul +// 19 Feb 2009 + + +// This test could be better: +// 1. Generate random state vectors, render and compare to expected values +// 2. Exercise separate front/back reference values and masks for the +// EXT and GL2 variations. + + + +#include <cassert> +#include <cstring> +#include "tstencil2.h" + + +namespace GLEAN { + +// ATI +static PFNGLSTENCILOPSEPARATEATIPROC glStencilOpSeparateATI_func; +static PFNGLSTENCILFUNCSEPARATEATIPROC glStencilFuncSeparateATI_func; + +// EXT +static PFNGLACTIVESTENCILFACEEXTPROC glActiveStencilFaceEXT_func; + +// GL2 +static PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate_func; +static PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate_func; +static PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate_func; + + +// two-sided methods: +#define ATI 1 +#define EXT 2 +#define GL2 3 + + +Stencil2Result::Stencil2Result() +{ + pass = false; +} + + +void +Stencil2Test::get_ext_functions(void) +{ + // ATI + glStencilOpSeparateATI_func = (PFNGLSTENCILOPSEPARATEATIPROC) + GLUtils::getProcAddress("glStencilOpSeparateATI"); + glStencilFuncSeparateATI_func = (PFNGLSTENCILFUNCSEPARATEATIPROC) + GLUtils::getProcAddress("glStencilFuncSeparateATI"); + + // EXT + glActiveStencilFaceEXT_func = (PFNGLACTIVESTENCILFACEEXTPROC) + GLUtils::getProcAddress("glActiveStencilFaceEXT"); + + // GL2 + glStencilOpSeparate_func = (PFNGLSTENCILOPSEPARATEPROC) + GLUtils::getProcAddress("glStencilOpSeparate"); + + glStencilFuncSeparate_func = (PFNGLSTENCILFUNCSEPARATEPROC) + GLUtils::getProcAddress("glStencilFuncSeparate"); + + glStencilMaskSeparate_func= (PFNGLSTENCILMASKSEPARATEPROC) + GLUtils::getProcAddress("glStencilMaskSeparate"); +} + + +bool +Stencil2Test::have_ATI_separate_stencil(void) const +{ + return GLUtils::haveExtension("GL_ATI_separate_stencil"); +} + +bool +Stencil2Test::have_EXT_stencil_two_side(void) const +{ + return GLUtils::haveExtension("GL_EXT_stencil_two_side"); +} + +bool +Stencil2Test::have_GL2_stencil_two_side(void) const +{ + const char *version = (const char *) glGetString(GL_VERSION); + if (strncmp(version, "2.", 2) == 0 || + strncmp(version, "3.0", 3) == 0) { + return true; + } + return false; +} + +bool +Stencil2Test::have_stencil_wrap(void) const +{ + const char *version = (const char *) glGetString(GL_VERSION); + if (strncmp(version, "2.", 2) == 0 || + strncmp(version, "3.0", 3) == 0) { + return true; + } + else if (GLUtils::haveExtension("GL_EXT_stencil_wrap")) { + return true; + } + return false; +} + + +// Draw four quads: +// Bottom row uses GL_CCW +// Top row uses GL_CW +// Left column is front-facing +// Right column is back-facing +// Check the values in the stencil buffer to see if they match +// the expected values. +bool +Stencil2Test::render_test(GLuint expectedFront, GLuint expectedBack) +{ + GLint x0 = 0; + GLint x1 = windowSize / 2; + GLint x2 = windowSize; + GLint y0 = 0; + GLint y1 = windowSize / 2; + GLint y2 = windowSize; + + glFrontFace(GL_CCW); // this the GL default + + // lower left quad = front-facing + glBegin(GL_TRIANGLE_FAN); + glVertex2f(x0, y0); + glVertex2f(x1, y0); + glVertex2f(x1, y1); + glVertex2f(x0, y1); + glEnd(); + + // lower right quad = back-facing + glBegin(GL_TRIANGLE_FAN); + glVertex2f(x1, y0); + glVertex2f(x1, y1); + glVertex2f(x2, y1); + glVertex2f(x2, y0); + glEnd(); + + glFrontFace(GL_CW); + + // upper left quad = front-facing + glBegin(GL_TRIANGLE_FAN); + glVertex2f(x0, y1); + glVertex2f(x0, y2); + glVertex2f(x1, y2); + glVertex2f(x1, y1); + glEnd(); + + // upper right quad = back-facing + glBegin(GL_TRIANGLE_FAN); + glVertex2f(x1, y1); + glVertex2f(x2, y1); + glVertex2f(x2, y2); + glVertex2f(x1, y2); + glEnd(); + + GLint midXleft = (x0 + x1) / 2; + GLint midXright = (x1 + x2) / 2; + GLint midYlower = (y0 + y1) / 2; + GLint midYupper = (y1 + y2) / 2; + GLuint lowerLeftVal, lowerRightVal; + GLuint upperLeftVal, upperRightVal; + + glReadPixels(midXleft, midYlower, 1, 1, + GL_STENCIL_INDEX, GL_UNSIGNED_INT, &lowerLeftVal); + glReadPixels(midXright, midYlower, 1, 1, + GL_STENCIL_INDEX, GL_UNSIGNED_INT, &lowerRightVal); + + glReadPixels(midXleft, midYupper, 1, 1, + GL_STENCIL_INDEX, GL_UNSIGNED_INT, &upperLeftVal); + glReadPixels(midXright, midYupper, 1, 1, + GL_STENCIL_INDEX, GL_UNSIGNED_INT, &upperRightVal); + + if (lowerLeftVal != upperLeftVal) { + env->log << "FAIL:\n"; + env->log << "\tLower-left value (" << lowerLeftVal + << ") doesn't match upper-left value (" + << upperLeftVal + << ").\n"; + env->log << "\tLooks like a front/back-face orientation bug.\n"; + return false; + } + + if (lowerRightVal != upperRightVal) { + env->log << "FAIL:\n"; + env->log << "\tLower-right value (" << lowerRightVal + << ") doesn't match upper-right value (" + << upperRightVal + << ").\n"; + env->log << "\tLooks like a front/back-face orientation bug.\n"; + return false; + } + + + if (lowerLeftVal != expectedFront) { + env->log << "FAIL:\n"; + env->log << "\tExpected front-face stencil value is " + << expectedFront + << " but found " << lowerLeftVal << "\n"; + return false; + } + else if (lowerRightVal != expectedBack) { + env->log << "FAIL:\n"; + env->log << "\tExpected back-face stencil value is " << expectedBack + << " but found " << lowerRightVal << "\n"; + return false; + } + else { + return true; + } +} + + +bool +Stencil2Test::compare_state(int method, GLenum found, GLenum expected, + const char *msg) +{ + if (found != expected) { + env->log << "FAIL:\n"; + env->log << "\tQuery of " << msg << " state failed for "; + switch (method) { + case ATI: + env->log << "GL_ATI_separate_stencil"; + break; + case EXT: + env->log << "GL_EXT_stencil_two_side"; + break; + case GL2: + env->log << "GL 2.x two-sided stencil"; + break; + default: + assert(0); + } + env->log << "\n"; + char s[1000]; + sprintf(s, "\tFound 0x%x, expected 0x%x\n", found, expected); + env->log << s; + return false; + } + return true; +} + + +// Set stencil state, plus read it back and check that it's correct. +// Note: we only test with one reference value and one mask value +// even though EXT and GL2 support separate front/back refs/masks +bool +Stencil2Test::set_stencil_state(int method, + GLenum frontStencilFail, + GLenum backStencilFail, + GLenum frontZFail, + GLenum backZFail, + GLenum frontZPass, + GLenum backZPass, + GLenum frontFunc, + GLenum backFunc, + GLint ref, + GLuint mask) +{ + GLint get_frontStencilFail; + GLint get_backStencilFail; + GLint get_frontZFail; + GLint get_backZFail; + GLint get_frontZPass; + GLint get_backZPass; + GLint get_frontFunc; + GLint get_backFunc; + GLint get_ref; + GLint get_mask; + GLint twoEnabled; + + switch (method) { + case ATI: + // set state + glStencilOpSeparateATI_func(GL_FRONT, + frontStencilFail, + frontZFail, + frontZPass); + + glStencilOpSeparateATI_func(GL_BACK, + backStencilFail, + backZFail, + backZPass); + + glStencilFuncSeparateATI_func(frontFunc, backFunc, ref, mask); + + // get state + glGetIntegerv(GL_STENCIL_FAIL, &get_frontStencilFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &get_frontZFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &get_frontZPass); + glGetIntegerv(GL_STENCIL_FUNC, &get_frontFunc); + glGetIntegerv(GL_STENCIL_REF, &get_ref); + glGetIntegerv(GL_STENCIL_VALUE_MASK, &get_mask); + + glGetIntegerv(GL_STENCIL_BACK_FUNC_ATI, &get_backFunc); + glGetIntegerv(GL_STENCIL_BACK_FAIL_ATI, &get_backStencilFail); + glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI, &get_backZFail); + glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI, &get_backZPass); + twoEnabled = GL_TRUE; + break; + + case EXT: + // set state + glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); + + glActiveStencilFaceEXT_func(GL_FRONT); + glStencilOp(frontStencilFail, frontZFail, frontZPass); + glStencilFunc(frontFunc, ref, mask); + + glActiveStencilFaceEXT_func(GL_BACK); + glStencilOp(backStencilFail, backZFail, backZPass); + glStencilFunc(backFunc, ref, mask); + + // get state + glActiveStencilFaceEXT_func(GL_FRONT); + glGetIntegerv(GL_STENCIL_FAIL, &get_frontStencilFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &get_frontZFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &get_frontZPass); + glGetIntegerv(GL_STENCIL_FUNC, &get_frontFunc); + glGetIntegerv(GL_STENCIL_REF, &get_ref); + glGetIntegerv(GL_STENCIL_VALUE_MASK, &get_mask); + glActiveStencilFaceEXT_func(GL_BACK); + glGetIntegerv(GL_STENCIL_FAIL, &get_backStencilFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &get_backZFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &get_backZPass); + glGetIntegerv(GL_STENCIL_FUNC, &get_backFunc); + glGetIntegerv(GL_STENCIL_REF, &get_ref); + glGetIntegerv(GL_STENCIL_VALUE_MASK, &get_mask); + glGetIntegerv(GL_STENCIL_TEST_TWO_SIDE_EXT, &twoEnabled); + break; + + case GL2: + // set state + glStencilOpSeparate_func(GL_FRONT, + frontStencilFail, + frontZFail, + frontZPass); + glStencilOpSeparate_func(GL_BACK, + backStencilFail, + backZFail, + backZPass); + glStencilFuncSeparate_func(GL_FRONT, frontFunc, ref, mask); + glStencilFuncSeparate_func(GL_BACK, backFunc, ref, mask); + + // get state + glGetIntegerv(GL_STENCIL_FAIL, &get_frontStencilFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &get_frontZFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &get_frontZPass); + glGetIntegerv(GL_STENCIL_FUNC, &get_frontFunc); + glGetIntegerv(GL_STENCIL_REF, &get_ref); + glGetIntegerv(GL_STENCIL_VALUE_MASK, &get_mask); + + glGetIntegerv(GL_STENCIL_BACK_FUNC, &get_backFunc); + glGetIntegerv(GL_STENCIL_BACK_FAIL, &get_backStencilFail); + glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &get_backZFail); + glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &get_backZPass); + twoEnabled = GL_TRUE; + break; + + default: + assert(0); + } + + // mask off bits we don't care about + get_mask &= stencilMax; + mask &= stencilMax; + + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + env->log << "FAIL:\n"; + env->log << "\tGL error " << err << " detected.\n"; + return false; + } + + // see if state-get matches state-set + + if (!compare_state(method, get_frontStencilFail, frontStencilFail, + "front stencil fail")) + return false; + + if (!compare_state(method, get_backStencilFail, backStencilFail, + "back stencil fail")) + return false; + + if (!compare_state(method, get_frontZFail, frontZFail, + "front Z fail")) + return false; + + if (!compare_state(method, get_backZFail, backZFail, + "back Z fail")) + return false; + + if (!compare_state(method, get_frontZPass, frontZPass, + "front Z pass")) + return false; + + if (!compare_state(method, get_backZPass, backZPass, + "back Z pass")) + return false; + + if (!compare_state(method, get_frontFunc, frontFunc, + "front stencil func")) + return false; + + if (!compare_state(method, get_backFunc, backFunc, + "back stencil func")) + return false; + + if (!compare_state(method, get_ref, ref, "stencil ref")) + return false; + + if (!compare_state(method, get_mask, mask, "stencil mask")) + return false; + + if (!compare_state(method, twoEnabled, GL_TRUE, "two-side enable")) + return false; + + return true; +} + + +void +Stencil2Test::reset_stencil_state(int method) +{ + switch (method) { + case ATI: + break; + case EXT: + glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + glActiveStencilFaceEXT_func(GL_FRONT); + break; + case GL2: + break; + default: + assert(0); + } +} + + +bool +Stencil2Test::test_stencil(int method) +{ + bool pass; + + glEnable(GL_STENCIL_TEST); + + //============================================================ + // No depth testing + glDisable(GL_DEPTH_TEST); + + glClear(GL_COLOR_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT); + + + // set stencil buffer vals to 5 + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_REPLACE, GL_REPLACE, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 5, ~0); // ref, mask + if (pass) + pass = render_test(5, 5); + reset_stencil_state(method); + if (!pass) + return false; + + // incr front val to 6, decr back val to 4 + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_INCR, GL_DECR, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 5, ~0); // ref, mask + if (pass) + pass = render_test(6, 4); + reset_stencil_state(method); + if (!pass) + return false; + + // if front==6, keep + // if back<6, replace with zero + // final: front=6, back=0 + pass = set_stencil_state(method, + GL_KEEP, GL_ZERO, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_KEEP, GL_KEEP, // z pass + GL_EQUAL, GL_LESS, // stencil func + 6, ~0); // ref, mask + if (pass) + pass = render_test(6, 0); + reset_stencil_state(method); + if (!pass) + return false; + + // if front!=10, keep, else decr + // if back<10, keep, else incr + // final: front=6, back=1 + pass = set_stencil_state(method, + GL_DECR, GL_INCR, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_KEEP, GL_KEEP, // z pass + GL_NOTEQUAL, GL_LESS, // stencil func + 10, ~0); // ref, mask + if (pass) + pass = render_test(6, 1); + reset_stencil_state(method); + if (!pass) + return false; + + + //============================================================ + // Now begin tests with depth test + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glClear(GL_COLOR_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT); + + // set stencil buffer vals to 7, set Z values + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_REPLACE, GL_REPLACE, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 7, ~0); // ref, mask + if (pass) + pass = render_test(7, 7); + reset_stencil_state(method); + if (!pass) + return false; + + + // GL_LESS test should fail everywhere + // decr front to 5, incr back to 2 + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_DECR, GL_INCR, // z fail + GL_KEEP, GL_KEEP, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 99, ~0); // ref, mask + if (pass) + pass = render_test(6, 8); + reset_stencil_state(method); + if (!pass) + return false; + + + // set depth test = GL_EQUAL + // Z test should pass everywhere + // set front to 3 + // decr back to 7 + glDepthFunc(GL_EQUAL); + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_REPLACE, GL_DECR, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 3, ~0); // ref, mask + if (pass) + pass = render_test(3, 7); + reset_stencil_state(method); + if (!pass) + return false; + + + // incr front to 4 (by z pass), decr back to 6 (by stencil fail) + pass = set_stencil_state(method, + GL_DECR, GL_INCR, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_INCR, GL_DECR, // z pass + GL_EQUAL, GL_NOTEQUAL, // stencil func + 3, ~0); // ref, mask + if (pass) + pass = render_test(4, 6); + reset_stencil_state(method); + if (!pass) + return false; + + + //============================================================ + // Disable depth test + glDisable(GL_DEPTH_TEST); + + // test stencil value mask + // only test bit 1 in stencil values + // if !(front&0x2 == 15&0x2), decr to 3 (should happen) + // if !(back&0x2 == 15&0x2), incr to 7 (should not happen) + pass = set_stencil_state(method, + GL_DECR, GL_INCR, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_KEEP, GL_KEEP, // z pass + GL_EQUAL, GL_EQUAL, // stencil func + 15, 0x2); // ref, mask + if (pass) + pass = render_test(3, 6); + reset_stencil_state(method); + if (!pass) + return false; + + + //============================================================ + // Test common two-sided stencil modes for shadow volume rendering + // Requires stencil +/- wrap feature. + + if (!have_stencil_wrap()) + return true; + + glClear(GL_COLOR_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + // "traditional / Z-pass" method: + // front face: incr on zpass + // back face: decr on zpass + // both front and back Z-test should pass here + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_KEEP, GL_KEEP, // z fail + GL_INCR_WRAP_EXT, GL_DECR_WRAP_EXT, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 0, ~0); // ref, mask + if (pass) + pass = render_test(1, stencilMax); + reset_stencil_state(method); + if (!pass) + return false; + + + // "Z-fail" method: + // front face: decr on zfail + // back face: incr on zfail + // both front and back Z-test should fail here + pass = set_stencil_state(method, + GL_KEEP, GL_KEEP, // stencil fail + GL_DECR_WRAP_EXT, GL_INCR_WRAP_EXT, // z fail + GL_KEEP, GL_KEEP, // z pass + GL_ALWAYS, GL_ALWAYS, // stencil func + 0, ~0); // ref, mask + if (pass) + pass = render_test(0, 0); + reset_stencil_state(method); + if (!pass) + return false; + + + return true; +} + + +void +Stencil2Test::runOne(Stencil2Result &r, Window &w) +{ + (void) w; // silence warning + r.pass = true; + + get_ext_functions(); + + // how many stencil bits (we assume at least 8 above) + glGetIntegerv(GL_STENCIL_BITS, &stencilBits); + stencilMax = (1 << stencilBits) - 1; + assert(stencilBits >= 8); + + glViewport(0, 0, windowSize, windowSize); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, windowSize, 0, windowSize, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (have_ATI_separate_stencil()) { + r.pass &= test_stencil(ATI); + } + + if (have_EXT_stencil_two_side()) { + r.pass &= test_stencil(EXT); + } + + if (have_GL2_stencil_two_side()) { + r.pass &= test_stencil(GL2); + } +} + + +void +Stencil2Test::logOne(Stencil2Result &r) +{ + logPassFail(r); + logConcise(r); +} + + +void +Stencil2Test::compareOne(Stencil2Result &oldR, + Stencil2Result &stencil2R) +{ + comparePassFail(oldR, stencil2R); +} + + +void +Stencil2Result::putresults(ostream &s) const +{ + if (pass) { + s << "PASS\n"; + } + else { + s << "FAIL\n"; + } +} + + +bool +Stencil2Result::getresults(istream &s) +{ + char result[1000]; + s >> result; + + if (strcmp(result, "FAIL") == 0) { + pass = false; + } + else { + pass = true; + } + return s.good(); +} + + +bool +Stencil2Test::isApplicable() const +{ + return (have_ATI_separate_stencil() || + have_EXT_stencil_two_side() || + have_EXT_stencil_two_side()); +} + + + +// The test object itself: +Stencil2Test stencil2Test("stencil2", + "window, rgb, s, z", // we need stencil and Z + "", // no extension filter, but see isApplicable() + "Test two-sided stencil features\n"); + + + +} // namespace GLEAN diff --git a/tests/glean/tstencil2.h b/tests/glean/tstencil2.h new file mode 100644 index 000000000..8c332cda2 --- /dev/null +++ b/tests/glean/tstencil2.h @@ -0,0 +1,95 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + +// tstencil2.h: Test two-sided stencil features + +#ifndef __tstencil2_h__ +#define __tstencil2_h__ + +#include "tbase.h" + +namespace GLEAN { + +#define windowSize 100 + +class Stencil2Result: public BaseResult +{ +public: + bool pass; + + Stencil2Result(); + + virtual void putresults(ostream& s) const; + virtual bool getresults(istream& s); +}; + + +class Stencil2Test: public BaseTest<Stencil2Result> +{ +public: + GLEAN_CLASS_WH(Stencil2Test, Stencil2Result, + windowSize, windowSize); + + bool isApplicable() const; + +private: + GLint stencilBits, stencilMax; + + void get_ext_functions(); + + bool have_ATI_separate_stencil(void) const; + bool have_EXT_stencil_two_side(void) const; + bool have_GL2_stencil_two_side(void) const; + bool have_stencil_wrap(void) const; + + bool render_test(GLuint expectedFront, GLuint expectedBack); + + bool compare_state(int method, GLenum found, GLenum expected, const char *msg); + + bool set_stencil_state(int method, + GLenum frontStencilFail, + GLenum backStencilFail, + GLenum frontZFail, + GLenum backZFail, + GLenum frontZPass, + GLenum backZPass, + GLenum frontFunc, + GLenum backFunc, + GLint ref, + GLuint mask); + + void reset_stencil_state(int method); + + bool test_stencil(GLint method); + +}; + +} // namespace GLEAN + +#endif // __tstencil2_h__ + diff --git a/tests/glean/ttexcombine4.cpp b/tests/glean/ttexcombine4.cpp new file mode 100644 index 000000000..1173d523c --- /dev/null +++ b/tests/glean/ttexcombine4.cpp @@ -0,0 +1,424 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +// Test GL_NV_texture_env_combine4 +// Generate some random combiner state and colors, compute the expected +// color, then render with the combiner state and compare the results. +// Only one texture unit is tested and not all possible combiner terms +// are exercised. +// +// Brian Paul +// 23 Jan 2009 + + +#define GL_GLEXT_PROTOTYPES + +#include <cassert> +#include <cmath> +#include <cstring> +#include "ttexcombine4.h" +#include "timer.h" + + +namespace GLEAN { + +TexCombine4Result::TexCombine4Result() +{ + pass = true; +} + + +// generate random combiner state +void +TexCombine4Test::generate_state(struct combine_state &state) +{ + int i; + + if (rand.next() > 0.5f) + state.CombineMode = GL_ADD; + else + state.CombineMode = GL_ADD_SIGNED_EXT; + + for (i = 0; i < 4; i++) { + int src = int(rand.next() * 4.0); + switch (src) { + case 0: + state.Source[i] = GL_ZERO; + break; + case 1: + state.Source[i] = GL_TEXTURE; + break; + case 2: + state.Source[i] = GL_CONSTANT_EXT; + break; + default: + state.Source[i] = GL_PRIMARY_COLOR_EXT; + break; + } + + if (rand.next() > 0.5f) { + state.OperandRGB[i] = GL_SRC_COLOR; + state.OperandA[i] = GL_SRC_ALPHA; + } + else { + state.OperandRGB[i] = GL_ONE_MINUS_SRC_COLOR; + state.OperandA[i] = GL_ONE_MINUS_SRC_ALPHA; + } + } + + state.PrimaryColor[0] = rand.next(); + state.PrimaryColor[1] = rand.next(); + state.PrimaryColor[2] = rand.next(); + state.PrimaryColor[3] = rand.next(); + + state.ConstantColor[0] = rand.next(); + state.ConstantColor[1] = rand.next(); + state.ConstantColor[2] = rand.next(); + state.ConstantColor[3] = rand.next(); + + state.TextureColor[0] = rand.next(); + state.TextureColor[1] = rand.next(); + state.TextureColor[2] = rand.next(); + state.TextureColor[3] = rand.next(); +} + + +// compute expected final color +void +TexCombine4Test::evaluate_state(const struct combine_state &state, + GLfloat result[4]) +{ + GLfloat arg[4][4]; + int i; + + // setup terms + for (i = 0; i < 4; i++) { + switch (state.Source[i]) { + case GL_ZERO: + arg[i][0] = arg[i][1] = arg[i][2] = arg[i][3] = 0.0f; + break; + case GL_PRIMARY_COLOR_EXT: + arg[i][0] = state.PrimaryColor[0]; + arg[i][1] = state.PrimaryColor[1]; + arg[i][2] = state.PrimaryColor[2]; + arg[i][3] = state.PrimaryColor[3]; + break; + case GL_CONSTANT_EXT: + arg[i][0] = state.ConstantColor[0]; + arg[i][1] = state.ConstantColor[1]; + arg[i][2] = state.ConstantColor[2]; + arg[i][3] = state.ConstantColor[3]; + break; + case GL_TEXTURE: + arg[i][0] = state.TextureColor[0]; + arg[i][1] = state.TextureColor[1]; + arg[i][2] = state.TextureColor[2]; + arg[i][3] = state.TextureColor[3]; + break; + default: + assert(0); + } + + switch (state.OperandRGB[i]) { + case GL_SRC_COLOR: + // nop + break; + case GL_ONE_MINUS_SRC_COLOR: + arg[i][0] = 1.0f - arg[i][0]; + arg[i][1] = 1.0f - arg[i][1]; + arg[i][2] = 1.0f - arg[i][2]; + arg[i][3] = 1.0f - arg[i][3]; + break; + default: + assert(0); + } + } + + // combine terms, loop over color channels + for (i = 0; i < 4; i++) { + result[i] = arg[0][i] * arg[1][i] + arg[2][i] * arg[3][i]; + if (state.CombineMode == GL_ADD_SIGNED_EXT) + result[i] -= 0.5f; + if (result[i] < 0.0f) + result[i] = 0.0f; + else if (result[i] > 1.0f) + result[i] = 1.0f; + } +} + + +// render quad with given combiner state and return resulting color +// return false if GL error is detected, true otherwise. +bool +TexCombine4Test::render_state(const struct combine_state &state, + GLfloat result[4]) +{ + if (glGetError()) { + reportError("GL error detected before setting combiner state."); + return false; + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV); + + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, state.CombineMode); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, state.CombineMode); + + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, state.Source[0]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, state.Source[0]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, state.Source[1]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, state.Source[1]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, state.Source[2]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, state.Source[2]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, state.Source[3]); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, state.Source[3]); + + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, state.OperandRGB[0]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, state.OperandA[0]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, state.OperandRGB[1]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, state.OperandA[1]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, state.OperandRGB[2]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, state.OperandA[2]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, state.OperandRGB[3]); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, state.OperandA[3]); + + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, state.ConstantColor); + + if (glGetError()) { + reportError("GL error generated by combiner state."); + return false; + } + + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, + GL_RGBA, GL_FLOAT, state.TextureColor); + + glColor4fv(state.PrimaryColor); + + glClear(GL_COLOR_BUFFER_BIT); + glBegin(GL_POLYGON); + glTexCoord2f(0.0, 0.0); + glVertex2f(-1.0, -1.0); + glTexCoord2f(1.0, 0.0); + glVertex2f(1.0, -1.0); + glTexCoord2f(1.0, 1.0); + glVertex2f( 1.0, 1.0); + glTexCoord2f(0.0, 1.0); + glVertex2f(-1.0, 1.0); + glEnd(); + + glReadPixels(WINDOW_SIZE / 2, WINDOW_SIZE / 2, 1, 1, + GL_RGBA, GL_FLOAT, result); + + return true; +} + + +void +TexCombine4Test::report_state(const struct combine_state &state) +{ + env->log << "\tCurrent GL state:\n"; + + if (state.CombineMode == GL_ADD) + env->log << "\t\tCOMBINE = GL_ADD\n"; + else + env->log << "\t\tCOMBINE = GL_ADD_SIGNED_EXT\n"; + + for (int i = 0; i < 4; i++) { + env->log << "\t\t" << "SOURCE" << i << ": "; + switch (state.Source[i]) { + case GL_ZERO: + env->log << "GL_ZERO\n"; + break; + case GL_TEXTURE: + env->log << "GL_TEXTURE\n"; + break; + case GL_CONSTANT_EXT: + env->log << "GL_CONSTANT\n"; + break; + case GL_PRIMARY_COLOR_EXT: + env->log << "GL_PRIMARY_COLOR\n"; + break; + default: + assert(0); + } + + env->log << "\t\t" << "OPERAND" << i << "_RGB: "; + switch (state.OperandRGB[i]) { + case GL_SRC_COLOR: + env->log << "GL_SRC_COLOR\n"; + break; + case GL_ONE_MINUS_SRC_COLOR: + env->log << "GL_ONE_MINUS_SRC_COLOR\n"; + break; + default: + assert(0); + } + + env->log << "\t\t" << "OPERAND" << i << "_ALPHA: "; + switch (state.OperandRGB[i]) { + case GL_SRC_COLOR: + env->log << "GL_SRC_ALPHA\n"; + break; + case GL_ONE_MINUS_SRC_COLOR: + env->log << "GL_ONE_MINUS_SRC_ALPHA\n"; + break; + default: + assert(0); + } + + } + + char str[100]; + sprintf(str, "%.3f, %.3f, %.3f, %.3f", + state.PrimaryColor[0], state.PrimaryColor[1], + state.PrimaryColor[2], state.PrimaryColor[3]); + env->log << "\t\tPrimary Color: " << str << "\n"; + sprintf(str, "%.3f, %.3f, %.3f, %.3f", + state.ConstantColor[0], state.ConstantColor[1], + state.ConstantColor[2], state.ConstantColor[3]); + env->log << "\t\tConstant Color: " << str << "\n"; + sprintf(str, "%.3f, %.3f, %.3f, %.3f", + state.TextureColor[0], state.TextureColor[1], + state.TextureColor[2], state.TextureColor[3]); + env->log << "\t\tTexture Color: " << str << "\n"; +} + + +void +TexCombine4Test::reportError(const char *msg) +{ + env->log << name << ": Error: " << msg << "\n"; +} + + +void +TexCombine4Test::runOne(TexCombine4Result &r, Window &w) +{ + (void) w; // silence warning + + rand = RandomDouble(42); // init random number generator + + const float err = 0.05; // xxx compute something better + + for (int i = 0; i < NUM_TESTS; i++) { + combine_state state; + GLfloat expected[4], actual[4]; + + //env->log << "\t iteration " << i << "\n"; + + generate_state(state); + + evaluate_state(state, expected); + + if (!render_state(state, actual)) { + r.pass = false; + return; + } + + if (fabs(expected[0] - actual[0]) > err || + fabs(expected[1] - actual[1]) > err || + fabs(expected[2] - actual[2]) > err) { + char str[100]; + env->log << name << ": Error: GL_NV_texure_env_combine4 failed\n"; + report_state(state); + env->log << "\tResults:\n"; + sprintf(str, "%.3f, %.3f, %.3f, %.3f", + expected[0], expected[1], + expected[2], expected[3]); + env->log << "\t\tExpected color: " << str << "\n"; + sprintf(str, "%.3f, %.3f, %.3f, %.3f", + actual[0], actual[1], + actual[2], actual[3]); + env->log << "\t\tRendered color: " << str << "\n"; + r.pass = false; + return; + } + } + + r.pass = true; +} + + +void +TexCombine4Test::logOne(TexCombine4Result &r) +{ + logPassFail(r); + logConcise(r); +} + + +void +TexCombine4Test::compareOne(TexCombine4Result &oldR, + TexCombine4Result &newR) +{ + comparePassFail(oldR, newR); +} + + +void +TexCombine4Result::putresults(ostream &s) const +{ + if (pass) { + s << "PASS\n"; + } + else { + s << "FAIL\n"; + } +} + + +bool +TexCombine4Result::getresults(istream &s) +{ + char result[1000]; + s >> result; + + if (strcmp(result, "FAIL") == 0) { + pass = false; + } + else { + pass = true; + } + return s.good(); +} + + +// The test object itself: +TexCombine4Test texCombine4Test("texCombine4", "window, rgb", + "GL_NV_texture_env_combine4, GL_EXT_texture_env_combine", + "Test the GL_NV_texture_env_combine4 extension.\n"); + + + +} // namespace GLEAN + + diff --git a/tests/glean/ttexcombine4.h b/tests/glean/ttexcombine4.h new file mode 100644 index 000000000..f6d323ee6 --- /dev/null +++ b/tests/glean/ttexcombine4.h @@ -0,0 +1,88 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + +// ttexcombine4.h: Test GL_NV_texture_env_combine4 + +#ifndef __ttexcombine4_h__ +#define __ttexcombine4_h__ + +#include "tbase.h" +#include "rand.h" + + +namespace GLEAN { + +#define NUM_POINTS 1000 +#define WINDOW_SIZE 100 +#define NUM_TESTS 200 + + +class TexCombine4Result: public BaseResult +{ +public: + TexCombine4Result(); + + virtual void putresults(ostream& s) const; + virtual bool getresults(istream& s); + + bool pass; +}; + + +class TexCombine4Test: public BaseTest<TexCombine4Result> +{ +public: + GLEAN_CLASS_WH(TexCombine4Test, TexCombine4Result, + WINDOW_SIZE, WINDOW_SIZE); + +private: + struct combine_state + { + GLenum CombineMode; + GLenum Source[4]; + GLenum OperandRGB[4]; + GLenum OperandA[4]; + GLfloat PrimaryColor[4]; + GLfloat ConstantColor[4]; + GLfloat TextureColor[4]; + }; + + RandomDouble rand; + + void generate_state(struct combine_state &state); + void evaluate_state(const struct combine_state &state, GLfloat result[4]); + bool render_state(const struct combine_state &state, GLfloat result[4]); + void report_state(const struct combine_state &state); + + void reportError(const char *msg); +}; + +} // namespace GLEAN + +#endif // __ttexcombine4_h__ + diff --git a/tests/glean/ttexenv.cpp b/tests/glean/ttexenv.cpp index 223f53cfb..6a8f8d886 100644 --- a/tests/glean/ttexenv.cpp +++ b/tests/glean/ttexenv.cpp @@ -40,10 +40,12 @@ // post-texture alpha value is correct. // -#include "ttexenv.h" +#include <stdlib.h> #include <cassert> #include <stdio.h> #include <cmath> +#include "ttexenv.h" + namespace GLEAN { diff --git a/tests/glean/ttexswizzle.cpp b/tests/glean/ttexswizzle.cpp new file mode 100644 index 000000000..6bd1304a9 --- /dev/null +++ b/tests/glean/ttexswizzle.cpp @@ -0,0 +1,456 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +// Test GL_EXT_texture_swizzle for all possible swizzle combinations +// both with fixed function and a fragment program. +// Brian Paul +// 28 Jan 2009 + + +#define GL_GLEXT_PROTOTYPES + +#include <cassert> +#include <cmath> +#include <cstring> +#include <stdlib.h> +#include "ttexswizzle.h" +#include "rand.h" +#include "timer.h" +#include "image.h" + + +// In case glext.h isn't new enough: +#ifndef GL_EXT_texture_swizzle + +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 + +#endif + + +namespace GLEAN { + + +static const int TexSize = 16; + +static const GLfloat vertexData[4][4] = { + // x, y, s, t + { -1.0, -1.0, 0.0, 0.0 }, + { 1.0, -1.0, 1.0, 0.0 }, + { 1.0, 1.0, 1.0, 1.0 }, + { -1.0, 1.0, 0.0, 1.0 } +}; + + +TexSwizzleResult::TexSwizzleResult() +{ + pass = false; +} + + +void +TexSwizzleTest::RandomColor(GLubyte *color) +{ + color[0] = rand.next() & 0xff; + color[1] = rand.next() & 0xff; + color[2] = rand.next() & 0xff; + color[3] = rand.next() & 0xff; +} + + +void +TexSwizzleTest::SetTextureColor(const GLubyte *color) +{ + GLubyte texImage[TexSize][TexSize][4]; + int i, j; + + for (i = 0; i < TexSize; i++) { + for (j = 0; j < TexSize; j++) { + texImage[i][j][0] = color[0]; + texImage[i][j][1] = color[1]; + texImage[i][j][2] = color[2]; + texImage[i][j][3] = color[3]; + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexSize, TexSize, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texImage); +} + + +GLubyte +TexSwizzleTest::Swizzle(const GLubyte *texColor, GLenum swizzle) +{ + switch (swizzle) { + case GL_RED: + return texColor[0]; + case GL_GREEN: + return texColor[1]; + case GL_BLUE: + return texColor[2]; + case GL_ALPHA: + return texColor[3]; + case GL_ONE: + return 255; + case GL_ZERO: + return 0; + default: + assert(0); + } +} + + +void +TexSwizzleTest::ComputeExpectedColor(const GLubyte *texColor, + GLenum swizzleR, + GLenum swizzleG, + GLenum swizzleB, + GLenum swizzleA, + GLubyte *expectedColor) +{ + expectedColor[0] = Swizzle(texColor, swizzleR); + expectedColor[1] = Swizzle(texColor, swizzleG); + expectedColor[2] = Swizzle(texColor, swizzleB); + expectedColor[3] = Swizzle(texColor, swizzleA); +} + + +const char * +TexSwizzleTest::SwizzleString(GLenum swizzle) +{ + switch (swizzle) { + case GL_RED: + return "GL_RED"; + case GL_GREEN: + return "GL_GREEN"; + case GL_BLUE: + return "GL_BLUE"; + case GL_ALPHA: + return "GL_ALPHA"; + case GL_ZERO: + return "GL_ZERO"; + case GL_ONE: + return "GL_ONE"; + default: + assert(0); + return "???"; + } +} + + +void +TexSwizzleTest::ReportFailure(GLenum swizzleR, GLenum swizzleG, + GLenum swizzleB, GLenum swizzleA, + const GLubyte *texColor, + const GLubyte *actual, + const GLubyte *expected) +{ + char str[100]; + + env->log << name << ": Error: GL_EXT_texure_swizzle test failed\n"; + env->log << "\tGL_TEXTURE_SWIZZLE_R_EXT = " << SwizzleString(swizzleR) << "\n"; + env->log << "\tGL_TEXTURE_SWIZZLE_G_EXT = " << SwizzleString(swizzleG) << "\n"; + env->log << "\tGL_TEXTURE_SWIZZLE_B_EXT = " << SwizzleString(swizzleB) << "\n"; + env->log << "\tGL_TEXTURE_SWIZZLE_A_EXT = " << SwizzleString(swizzleA) << "\n"; + if (glIsEnabled(GL_FRAGMENT_PROGRAM_ARB)) { + env->log << "\tGL_FRAGMENT_PROGRAM enabled\n"; + } + sprintf(str, "%d, %d, %d, %d", + texColor[0], texColor[1], texColor[2], texColor[3]); + env->log << "\tTexture color: " << str << "\n"; + sprintf(str, "%d, %d, %d, %d", + expected[0], expected[1], expected[2], expected[3]); + env->log << "\tExpected color: " << str << "\n"; + sprintf(str, "%d, %d, %d, %d", + actual[0], actual[1], actual[2], actual[3]); + env->log << "\tRendered color: " << str << "\n"; +} + + +// Test state setting/getting for texture swizzle. +bool +TexSwizzleTest::TestAPI(void) +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R_EXT, GL_ONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G_EXT, GL_ZERO); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B_EXT, GL_RED); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A_EXT, GL_BLUE); + + if (glGetError() != GL_NO_ERROR) { + env->log << "\tSetting GL_TEXTURE_SWIZZLE_R/G/B/A generated an error.\n"; + return false; + } + + GLint val; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R_EXT, &val); + if (val != GL_ONE) { + env->log << "\tQuery of GL_TEXTURE_SWIZZLE_R_EXT failed.\n"; + return false; + } + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G_EXT, &val); + if (val != GL_ZERO) { + env->log << "\tQuery of GL_TEXTURE_SWIZZLE_G_EXT failed.\n"; + return false; + } + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B_EXT, &val); + if (val != GL_RED) { + env->log << "\tQuery of GL_TEXTURE_SWIZZLE_B_EXT failed.\n"; + return false; + } + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A_EXT, &val); + if (val != GL_BLUE) { + env->log << "\tQuery of GL_TEXTURE_SWIZZLE_A_EXT failed.\n"; + return false; + } + + // set all at once + const GLint swz[4] = { GL_BLUE, GL_GREEN, GL_ALPHA, GL_ZERO }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA_EXT, swz); + if (glGetError() != GL_NO_ERROR) { + env->log << "\tSetting GL_TEXTURE_SWIZZLE_RGBA_EXT generated an error.\n"; + return false; + } + + GLint swzOut[4]; + glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA_EXT, swzOut); + if (swzOut[0] != swz[0] || + swzOut[1] != swz[1] || + swzOut[2] != swz[2] || + swzOut[3] != swz[3]) { + env->log << "\tQuerying GL_TEXTURE_SWIZZLE_RGBA_EXT failed.\n"; + return false; + } + + return true; +} + + +// Loop over all possible combinations of texture swizzles, +// drawing with a texture and checking if the results are correct. +// return true/false for pass/fail +bool +TexSwizzleTest::TestSwizzles(void) +{ + static const GLenum swizzles[6] = { + GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO, GL_ONE + }; + int ir, ig, ib, ia; + GLubyte texColor[4]; + int err = 1; // XXX this should be computed from framebuffer depth + + for (ir = 0; ir < 6; ir++) { + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_SWIZZLE_R_EXT, + swizzles[ir]); + for (ig = 0; ig < 6; ig++) { + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_SWIZZLE_G_EXT, + swizzles[ig]); + + // Setup random texture color here (not in the innermost loop + // for _every_ iteration) just to speed things up a bit. + RandomColor(texColor); + SetTextureColor(texColor); + + for (ib = 0; ib < 6; ib++) { + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_SWIZZLE_B_EXT, + swizzles[ib]); + for (ia = 0; ia < 6; ia++) { + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_SWIZZLE_A_EXT, + swizzles[ia]); + + GLubyte expected[4]; + ComputeExpectedColor(texColor, + swizzles[ir], + swizzles[ig], + swizzles[ib], + swizzles[ia], + expected); + + // draw something and read back a pixel + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + GLubyte actual[4]; + glReadPixels(windowSize / 2, windowSize / 2, 1, 1, + GL_RGBA, GL_UNSIGNED_BYTE, actual); + + if (abs((int) actual[0] - (int) expected[0]) > err || + abs((int) actual[1] - (int) expected[1]) > err || + abs((int) actual[2] - (int) expected[2]) > err) { + + ReportFailure(swizzles[ir], + swizzles[ig], + swizzles[ib], + swizzles[ia], + texColor, actual, expected); + + return false; + } + } + } + } + } + + return true; +} + + +// Same test as above, but using a fragment program instead of fixed-function. +bool +TexSwizzleTest::TestSwizzlesWithProgram(void) +{ + const char *text = + "!!ARBfp1.0\n" + "TEX result.color, fragment.texcoord[0], texture[0], 2D; \n" + "END\n"; + GLuint prog; + + glGenProgramsARB(1, &prog); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(text), (const GLubyte *) text); + + assert(glGetError() == GL_NO_ERROR); + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + + bool pass = TestSwizzles(); + + glDisable(GL_FRAGMENT_PROGRAM_ARB); + + return pass; +} + + +void +TexSwizzleTest::Setup(void) +{ + // setup transformation + glViewport(0, 0, windowSize, windowSize); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // setup vertex arrays (draw textured quad) + glVertexPointer(2, GL_FLOAT, 16, vertexData); + glTexCoordPointer(2, GL_FLOAT, 16, &vertexData[0][2]); + glEnable(GL_VERTEX_ARRAY); + glEnable(GL_TEXTURE_COORD_ARRAY); + + // setup texture + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable(GL_TEXTURE_2D); +} + + +void +TexSwizzleTest::runOne(TexSwizzleResult &r, Window &w) +{ + (void) w; // silence warning + + Setup(); + + r.pass = TestAPI(); + + if (r.pass) { + r.pass = TestSwizzles(); + } + + if (r.pass && GLUtils::haveExtension("GL_ARB_fragment_program")) { + r. pass = TestSwizzlesWithProgram(); + } +} + + +void +TexSwizzleTest::logOne(TexSwizzleResult &r) +{ + if (r.pass) { + logPassFail(r); + logConcise(r); + } + else { + env->log << name << " FAIL\n"; + } +} + + +void +TexSwizzleTest::compareOne(TexSwizzleResult &oldR, + TexSwizzleResult &newR) +{ + comparePassFail(oldR, newR); +} + + +void +TexSwizzleResult::putresults(ostream &s) const +{ + if (pass) { + s << "PASS\n"; + } + else { + s << "FAIL\n"; + } +} + + +bool +TexSwizzleResult::getresults(istream &s) +{ + char result[1000]; + s >> result; + + if (strcmp(result, "FAIL") == 0) { + pass = false; + } + else { + pass = true; + } + return s.good(); +} + + +// The test object itself: +TexSwizzleTest texSwizzleTest("texSwizzle", "window, rgb", + "GL_EXT_texture_swizzle", + "Test the GL_EXT_texture_swizzle extension.\n"); + + + +} // namespace GLEAN + + diff --git a/tests/glean/ttexswizzle.h b/tests/glean/ttexswizzle.h new file mode 100644 index 000000000..efe394143 --- /dev/null +++ b/tests/glean/ttexswizzle.h @@ -0,0 +1,88 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + +// tTexSwizzle.h: Test GL_EXT_texture_swizzle + +#ifndef __ttexswizzle_h__ +#define __ttexswizzle_h__ + +#include "tbase.h" +#include "rand.h" + +namespace GLEAN { + +#define windowSize 50 + +class TexSwizzleResult: public BaseResult +{ +public: + bool pass; + + TexSwizzleResult(); + + virtual void putresults(ostream& s) const; + virtual bool getresults(istream& s); +}; + + +class TexSwizzleTest: public BaseTest<TexSwizzleResult> +{ +public: + GLEAN_CLASS_WH(TexSwizzleTest, TexSwizzleResult, + windowSize, windowSize); + +private: + RandomBase rand; + + void RandomColor(GLubyte *color); + void SetTextureColor(const GLubyte *color); + GLubyte Swizzle(const GLubyte *texColor, GLenum swizzle); + void ComputeExpectedColor(const GLubyte *texColor, + GLenum swizzleR, + GLenum swizzleG, + GLenum swizzleB, + GLenum swizzleA, + GLubyte *expectedColor); + const char *SwizzleString(GLenum swizzle); + void ReportFailure(GLenum swizzleR, + GLenum swizzleG, + GLenum swizzleB, + GLenum swizzleA, + const GLubyte *texColor, + const GLubyte *actual, + const GLubyte *expected); + bool TestAPI(void); + bool TestSwizzles(void); + bool TestSwizzlesWithProgram(void); + void Setup(void); +}; + +} // namespace GLEAN + +#endif // __ttexswizzle_h__ + diff --git a/tests/glean/ttexture_srgb.cpp b/tests/glean/ttexture_srgb.cpp index 809a56a6c..4fa5b9d1a 100644 --- a/tests/glean/ttexture_srgb.cpp +++ b/tests/glean/ttexture_srgb.cpp @@ -30,10 +30,12 @@ // Brian Paul August 2006 -#include "ttexture_srgb.h" -#include "rand.h" #include <cassert> +#include <cstring> #include <cmath> +#include "ttexture_srgb.h" +#include "rand.h" + #ifdef GL_EXT_texture_sRGB diff --git a/tests/glean/ttexunits.cpp b/tests/glean/ttexunits.cpp new file mode 100644 index 000000000..e84c94e1d --- /dev/null +++ b/tests/glean/ttexunits.cpp @@ -0,0 +1,323 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2008 VMWare, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + +// Test texture unit things +// We're generally just testing API-related things, not rendering. +// Brian Paul 31 Dec 2008 + +#define GL_GLEXT_PROTOTYPES + +#include <cstring> +#include <cassert> +#include <math.h> +#include "ttexunits.h" + + +namespace GLEAN { + + +void +TexUnitsTest::reportFailure(const char *msg) const +{ + env->log << "FAILURE:\n"; + env->log << "\t" << msg << "\n"; +} + + +void +TexUnitsTest::reportFailure(const char *msg, GLint unit) const +{ + char s[100]; + snprintf(s, sizeof(s), msg, unit); + env->log << "FAILURE:\n"; + env->log << "\t" << s << "\n"; +} + + +bool +TexUnitsTest::setup(void) +{ + // check that we have OpenGL 2.x or 3.x + const char *verString = (const char *) glGetString(GL_VERSION); + + if (verString[0] != '2' && verString[0] != '3') { + env->log << "OpenGL 2.x or 3.x not supported\n"; + return false; + } + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxImageUnits); + glGetIntegerv(GL_MAX_TEXTURE_COORDS, &maxCoordUnits); + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxUnits); + + return true; +} + + +bool +TexUnitsTest::testLimits(void) +{ + if (maxImageUnits < maxUnits) { + reportFailure("GL_MAX_TEXTURE_IMAGE_UNITS < GL_MAX_TEXTURE_UNITS"); + return false; + } + if (maxCoordUnits < maxUnits) { + reportFailure("GL_MAX_TEXTURE_COORD_UNITS < GL_MAX_TEXTURE_UNITS"); + return false; + } + return true; +} + + +bool +TexUnitsTest::testActiveTexture(void) +{ + GLint i; + GLint maxUnits; + + if (maxImageUnits > maxCoordUnits) + maxUnits = maxImageUnits; + else + maxUnits = maxCoordUnits; + + // clear any error state + while (glGetError()) + ; + + // test glActiveTexture() + for (i = 0; i < maxUnits; i++) { + glActiveTexture(GL_TEXTURE0 + i); + if (glGetError()) { + reportFailure("glActiveTexture(GL_TEXTURE%d) failed", i); + return false; + } + + GLint unit; + glGetIntegerv(GL_ACTIVE_TEXTURE, &unit); + if (unit != GL_TEXTURE0 + i || glGetError()) { + reportFailure("glGetIntegerv(GL_ACTIVE_TEXTURE) failed"); + return false; + } + } + + // this should fail: + glActiveTexture(GL_TEXTURE0 + maxUnits); + if (glGetError() != GL_INVALID_ENUM) { + reportFailure("glActiveTexture(GL_TEXTURE%d) failed to generate an error", + maxUnits); + return false; + } + + + // test glClientActiveTexture() + for (i = 0; i < maxCoordUnits; i++) { + glClientActiveTexture(GL_TEXTURE0 + i); + if (glGetError()) { + reportFailure("glClientActiveTexture(GL_TEXTURE%d) failed", i); + return false; + } + + GLint unit; + glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &unit); + if (unit != GL_TEXTURE0 + i || glGetError()) { + reportFailure("glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE) failed"); + return false; + } + } + + // this should fail: + glClientActiveTexture(GL_TEXTURE0 + maxUnits); + if (glGetError() != GL_INVALID_ENUM) { + reportFailure("glClientActiveTexture(GL_TEXTURE%d) failed to generate an error", maxUnits); + return false; + } + + return true; +} + + +bool +TexUnitsTest::testTextureMatrices(void) +{ + GLint i; + + glActiveTexture(GL_TEXTURE0); + glMatrixMode(GL_TEXTURE); + + // set texture matrices + for (i = 0; i < maxCoordUnits; i++) { + glActiveTexture(GL_TEXTURE0 + i); + + // generate matrix + GLfloat m[16]; + for (int j = 0; j < 16; j++) { + m[j] = float(i * 100 + j); + } + + glLoadMatrixf(m); + } + + // query texture matrices + for (i = 0; i < maxCoordUnits; i++) { + glActiveTexture(GL_TEXTURE0 + i); + + // get matrix and check it + GLfloat m[16]; + memset(m, 0, sizeof(m)); + glGetFloatv(GL_TEXTURE_MATRIX, m); + + if (glGetError()) { + reportFailure("Query of texture matrix %d raised an error", i); + return false; + } + + for (int j = 0; j < 16; j++) { + if (m[j] != float(i * 100 + j)) { + reportFailure("Query of texture matrix %d failed", i); + return false; + } + } + } + + if (glGetError()) { + reportFailure("GL error was generated while testing texture matrices"); + return false; + } + + return true; +} + + +bool +TexUnitsTest::testTextureCoordGen(void) +{ + GLint i; + + glActiveTexture(GL_TEXTURE0); + glMatrixMode(GL_TEXTURE); + + // test texgen enable/disable + for (i = 0; i < maxUnits; i++) { + glActiveTexture(GL_TEXTURE0 + i); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_Q); + if (i < maxCoordUnits) { + // should be no error + if (glGetError()) { + reportFailure("GL error was generated by enabling GL_TEXTURE_GEN_x, unit %d", i); + return false; + } + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_Q); + } + else { + // should be an error + if (glGetError() != GL_INVALID_OPERATION) { + reportFailure("GL error not generated by invalid enable of GL_TEXTURE_GEN_x, unit %d", i); + return false; + } + } + } + + return true; +} + + +bool +TexUnitsTest::testTexcoordArrays(void) +{ + GLint i; + + for (i = 0; i < maxCoordUnits; i++) { + glClientActiveTexture(GL_TEXTURE0 + i); + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + if (glGetError()) { + reportFailure("GL error was generated by glEnableClientState for unit %d", i); + return false; + } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + } + + return true; +} + + +void +TexUnitsTest::runOne(MultiTestResult &r, Window &w) +{ + (void) w; + + if (!setup()) { + r.pass = false; + return; + } + + if (testLimits()) + r.numPassed++; + else + r.numFailed++; + + if (testActiveTexture()) + r.numPassed++; + else + r.numFailed++; + + if (testTextureMatrices()) + r.numPassed++; + else + r.numFailed++; + + if (testTextureCoordGen()) + r.numPassed++; + else + r.numFailed++; + + if (testTexcoordArrays()) + r.numPassed++; + else + r.numFailed++; + + r.pass = (r.numFailed == 0); +} + + +// The test object itself: +TexUnitsTest texUnitTest("texUnits", "window, rgb", + "", // no extension filter + "texUnits: test texture units.\n" + ); + + + +} // namespace GLEAN diff --git a/tests/glean/ttexunits.h b/tests/glean/ttexunits.h new file mode 100644 index 000000000..803c515b6 --- /dev/null +++ b/tests/glean/ttexunits.h @@ -0,0 +1,70 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2008 VMware, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +#ifndef __ttexunits_h__ +#define __ttexunits_h__ + +#include "tmultitest.h" + +namespace GLEAN { + +#define windowSize 100 + + +class TexUnitsTest: public MultiTest +{ +public: + TexUnitsTest(const char* testName, const char* filter, + const char *extensions, const char* description): + MultiTest(testName, filter, extensions, description) + { + } + + virtual void runOne(MultiTestResult &r, Window &w); + +private: + GLint maxImageUnits; + GLint maxCoordUnits; + GLint maxUnits; + + void reportFailure(const char *msg) const; + void reportFailure(const char *msg, GLint unit) const; + + bool setup(void); + bool testLimits(void); + bool testActiveTexture(void); + bool testTextureMatrices(void); + bool testTextureCoordGen(void); + bool testTexcoordArrays(void); +}; + + +} // namespace GLEAN + +#endif // __ttexunits_h__ diff --git a/tests/glean/tvertarraybgra.cpp b/tests/glean/tvertarraybgra.cpp new file mode 100644 index 000000000..737af0c44 --- /dev/null +++ b/tests/glean/tvertarraybgra.cpp @@ -0,0 +1,248 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +// Render some geometry with random GLubyte/RGBA vertex colors. +// Then re-render same thing with GLubyte/BGRA vertex colors. +// Brian Paul +// 23 Jan 2009 + + +#define GL_GLEXT_PROTOTYPES + +#include <cassert> +#include <cmath> +#include <cstring> +#include "tvertarraybgra.h" +#include "rand.h" +#include "timer.h" +#include "image.h" + + +namespace GLEAN { + + +VertArrayBGRAResult::VertArrayBGRAResult() +{ + pass = true; +} + + +void +VertArrayBGRATest::reportError(const char *msg) +{ + env->log << name << ": Error: " << msg << "\n"; +} + + +bool +VertArrayBGRATest::testAPI(void) +{ + // Get glVertexAttrib() function + PFNGLVERTEXATTRIBPOINTERARBPROC VertexAttribPointer = NULL; + const char *version = (const char *) glGetString(GL_VERSION); + if (version[0] == '2') { + VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERARBPROC) + GLUtils::getProcAddress("glVertexAttribPointer"); + } + + GLubyte array[4]; + + if (glGetError()) { + reportError("initial error state is not GL_NO_ERROR."); + return false; + } + + glColorPointer(GL_BGRA, GL_UNSIGNED_BYTE, 0, array); + if (glGetError()) { + reportError("glColorPointer(size=GL_BGRA) generated an error."); + return false; + } + + glSecondaryColorPointer(GL_BGRA, GL_UNSIGNED_BYTE, 0, array); + if (glGetError()) { + reportError("glSecondaryColorPointer(size=GL_BGRA) generated an error."); + return false; + } + + if (VertexAttribPointer) { + VertexAttribPointer(2, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, array); + if (glGetError()) { + reportError("glVertexAttribPointer(size=GL_BGRA) generated an error."); + return false; + } + } + + // this _should_ generate an error + glColorPointer(GL_BGRA, GL_FLOAT, 0, array); + if (glGetError() != GL_INVALID_VALUE) { + reportError("glColorPointer(size=GL_BGRA, type=GL_FLOAT) did not generate expected error."); + return false; + } + + return true; +} + + +void +VertArrayBGRATest::setupPoints() +{ + RandomDouble r(10); + int i; + for (i = 0; i < NUM_POINTS; i++) { + mPos[i][0] = r.next() * WINDOW_SIZE; + mPos[i][1] = r.next() * WINDOW_SIZE; + mRGBA[i][0] = int(r.next() * 255); + mRGBA[i][1] = int(r.next() * 255); + mRGBA[i][2] = int(r.next() * 255); + mRGBA[i][3] = int(r.next() * 255); + mBGRA[i][0] = mRGBA[i][2]; // blue + mBGRA[i][1] = mRGBA[i][1]; // green + mBGRA[i][2] = mRGBA[i][0]; // red + mBGRA[i][3] = mRGBA[i][3]; // alpha + } +} + + +void +VertArrayBGRATest::renderPoints(bool useBGRA) +{ + glVertexPointer(2, GL_FLOAT, 0, mPos); + glEnable(GL_VERTEX_ARRAY); + + if (useBGRA) + glColorPointer(GL_BGRA, GL_UNSIGNED_BYTE, 0, mBGRA); + else + glColorPointer(4, GL_UNSIGNED_BYTE, 0, mRGBA); + glEnable(GL_COLOR_ARRAY); + + glDrawArrays(GL_POINTS, 0, NUM_POINTS); + + glDisable(GL_VERTEX_ARRAY); + glDisable(GL_COLOR_ARRAY); +} + + +void +VertArrayBGRATest::runOne(VertArrayBGRAResult &r, Window &w) +{ + (void) w; // silence warning + Image rgbaImage(WINDOW_SIZE, WINDOW_SIZE, GL_RGBA, GL_UNSIGNED_BYTE); + Image bgraImage(WINDOW_SIZE, WINDOW_SIZE, GL_RGBA, GL_UNSIGNED_BYTE); + + r.pass = testAPI(); + if (!r.pass) + return; + + setupPoints(); +#if 0 // test lighting path too (debug only) + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); +#endif + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, WINDOW_SIZE, 0, WINDOW_SIZE, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // render with RGBA colors and save image + glClear(GL_COLOR_BUFFER_BIT); + renderPoints(false); + rgbaImage.read(0, 0); // pos=(0,0) + w.swap(); + + // render with BGRA colors and save image + glClear(GL_COLOR_BUFFER_BIT); + renderPoints(true); + bgraImage.read(0, 0); // pos=(0,0) + w.swap(); + + // images should be identical + r.pass = (rgbaImage == bgraImage); + if (!r.pass) { + reportError("BGRA colors did not match RGBA colors."); + } +} + + +void +VertArrayBGRATest::logOne(VertArrayBGRAResult &r) +{ + logPassFail(r); + logConcise(r); +} + + +void +VertArrayBGRATest::compareOne(VertArrayBGRAResult &oldR, + VertArrayBGRAResult &newR) +{ + comparePassFail(oldR, newR); +} + + +void +VertArrayBGRAResult::putresults(ostream &s) const +{ + if (pass) { + s << "PASS\n"; + } + else { + s << "FAIL\n"; + } +} + + +bool +VertArrayBGRAResult::getresults(istream &s) +{ + char result[1000]; + s >> result; + + if (strcmp(result, "FAIL") == 0) { + pass = false; + } + else { + pass = true; + } + return s.good(); +} + + +// The test object itself: +VertArrayBGRATest vertArrayBGRATest("vertArrayBGRA", "window, rgb", + "GL_EXT_vertex_array_bgra", + "Test the GL_EXT_vertex_array_bgra extension.\n"); + + + +} // namespace GLEAN + + diff --git a/tests/glean/tvertarraybgra.h b/tests/glean/tvertarraybgra.h new file mode 100644 index 000000000..2b3a11845 --- /dev/null +++ b/tests/glean/tvertarraybgra.h @@ -0,0 +1,74 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 2009 VMware, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + +// tvertarraybgra.h: Test GL_EXT_vertex_array bgra + +#ifndef __tvertarraybgra_h__ +#define __tvertarraybgra_h__ + +#include "tbase.h" + + +namespace GLEAN { + +#define NUM_POINTS 1000 +#define WINDOW_SIZE 100 + +class VertArrayBGRAResult: public BaseResult +{ +public: + VertArrayBGRAResult(); + + virtual void putresults(ostream& s) const; + virtual bool getresults(istream& s); + + bool pass; +}; + + +class VertArrayBGRATest: public BaseTest<VertArrayBGRAResult> +{ +public: + GLEAN_CLASS_WH(VertArrayBGRATest, VertArrayBGRAResult, + WINDOW_SIZE, WINDOW_SIZE); + +private: + float mPos[NUM_POINTS][2]; + GLubyte mRGBA[NUM_POINTS][4]; + GLubyte mBGRA[NUM_POINTS][4]; + + void reportError(const char *msg); + bool testAPI(void); + void setupPoints(void); + void renderPoints(bool useBGRA); +}; + +} // namespace GLEAN + +#endif // __tvertarraybgra_h__ + diff --git a/tests/glean/tvertattrib.cpp b/tests/glean/tvertattrib.cpp index fd7e12cbe..6dadf9046 100644 --- a/tests/glean/tvertattrib.cpp +++ b/tests/glean/tvertattrib.cpp @@ -45,10 +45,11 @@ // Author: Brian Paul (brian.paul a t tungstengraphics.com) October 2004 +#include <stdlib.h> +#include <cassert> #include <math.h> #include "tvertattrib.h" #include "glutils.h" -#include <cassert> namespace GLEAN { diff --git a/tests/glean/tvertprog1.cpp b/tests/glean/tvertprog1.cpp index 9cfd52a4d..32053358d 100644 --- a/tests/glean/tvertprog1.cpp +++ b/tests/glean/tvertprog1.cpp @@ -31,10 +31,11 @@ // // See tfragprog.cpp for comments (this test is very similar). -#include "tvertprog1.h" #include <cassert> #include <cmath> +#include <cstring> #include <math.h> +#include "tvertprog1.h" namespace GLEAN { |