aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-03-07 03:36:21 -0800
committerEric Anholt <eric@anholt.net>2009-03-07 03:40:55 -0800
commite5fc8a140e66de7144cba57ab4737532573a5b3d (patch)
tree39a22b8af3d397a8e3a59482ac29712d237b7185
parentb74fa0389df84a1aa4d4495fc79bbd63fbd69bc5 (diff)
parentaa7c71facfe968af8f82c5a07b02cad039a3134e (diff)
Merge branch 'glean-master'
Conflicts: tests/glean/dsconfig.cpp tests/glean/dsfilt.cpp tests/glean/tapi2.cpp tests/glean/tdepthstencil.cpp tests/glean/tglsl1.cpp tests/glean/tlogicop.cpp tests/glean/toccluqry.cpp tests/glean/tpbo.cpp tests/glean/tpixelformats.cpp tests/glean/tpointsprite.cpp tests/glean/ttexture_srgb.cpp tests/glean/tvertattrib.cpp I decided to just take stock glean code where conflicts occurred. I kept delaying due to resolving the conflicts, and the only conflicts of value should be warning-related. Those should really be resolved upstream, instead.
-rw-r--r--tests/all.tests4
-rw-r--r--tests/glean/CMakeLists.txt4
-rw-r--r--tests/glean/dsconfig.cpp99
-rw-r--r--tests/glean/dsconfig.h5
-rw-r--r--tests/glean/dsfilt.cpp17
-rw-r--r--tests/glean/dsfilt.h4
-rw-r--r--tests/glean/glutils.cpp1
-rw-r--r--tests/glean/image.h5
-rw-r--r--tests/glean/image_misc.cpp26
-rw-r--r--tests/glean/main.cpp1
-rw-r--r--tests/glean/tapi2.cpp39
-rw-r--r--tests/glean/tbase.h34
-rw-r--r--tests/glean/tblend.cpp1
-rw-r--r--tests/glean/tdepthstencil.cpp7
-rw-r--r--tests/glean/tfbo.cpp46
-rw-r--r--tests/glean/tfbo.h1
-rw-r--r--tests/glean/tfpexceptions.cpp2
-rw-r--r--tests/glean/tfragprog1.cpp23
-rw-r--r--tests/glean/tglsl1.cpp158
-rw-r--r--tests/glean/tglsl1.h3
-rw-r--r--tests/glean/tlogicop.cpp22
-rw-r--r--tests/glean/toccluqry.cpp8
-rw-r--r--tests/glean/tpaths.cpp1
-rw-r--r--tests/glean/tpbo.cpp15
-rw-r--r--tests/glean/tpixelformats.cpp24
-rw-r--r--tests/glean/tpointsprite.cpp9
-rw-r--r--tests/glean/tshaderapi.cpp600
-rw-r--r--tests/glean/tshaderapi.h94
-rw-r--r--tests/glean/tstencil2.cpp785
-rw-r--r--tests/glean/tstencil2.h95
-rw-r--r--tests/glean/ttexcombine4.cpp424
-rw-r--r--tests/glean/ttexcombine4.h88
-rw-r--r--tests/glean/ttexenv.cpp4
-rw-r--r--tests/glean/ttexswizzle.cpp456
-rw-r--r--tests/glean/ttexswizzle.h88
-rw-r--r--tests/glean/ttexture_srgb.cpp7
-rw-r--r--tests/glean/ttexunits.cpp323
-rw-r--r--tests/glean/ttexunits.h70
-rw-r--r--tests/glean/tvertarraybgra.cpp248
-rw-r--r--tests/glean/tvertarraybgra.h74
-rw-r--r--tests/glean/tvertattrib.cpp9
41 files changed, 3791 insertions, 133 deletions
diff --git a/tests/all.tests b/tests/all.tests
index 26591a2d..e4a6c159 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -48,7 +48,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 aa59e56c..4090d975 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 16440b44..861c0c83 100644
--- a/tests/glean/dsconfig.cpp
+++ b/tests/glean/dsconfig.cpp
@@ -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
@@ -10,11 +12,11 @@
// 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
@@ -23,17 +25,17 @@
// 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
// dsconfig.cpp: Implementation of drawing surface configuration utilities
#include "dsconfig.h"
#include <iostream>
-#include <sstream>
-#include <cstring>
+#include <strstream>
+#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,
@@ -118,8 +121,7 @@ typedef enum { // These variable tags are used as array indices,
V_LAST
} CanonVar;
-struct CanonVarMapping {CanonVar var; const char* name;};
-CanonVarMapping varNames[] = {
+struct {CanonVar var; char* name;} varNames[] = {
{VID, "id"},
{VFBCID, "fbcID"},
{VCANRGBA, "canRGBA"},
@@ -139,6 +141,7 @@ CanonVarMapping varNames[] = {
{VACCUMG, "accumG"},
{VACCUMB, "accumB"},
{VACCUMA, "accumA"},
+ {VSAMPLES, "multisample"},
{VCANWINDOW, "window"},
{VCANPIXMAP, "pixmap"},
{VCANPBUFFER, "pBuffer"},
@@ -156,7 +159,7 @@ CanonVarMapping varNames[] = {
{VTRANSI, "transI"}
};
-const char* mapVarToName[V_LAST];
+char* mapVarToName[V_LAST];
map<string, CanonVar> mapNameToVar;
bool mapsInitialized = false;
@@ -229,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.
@@ -299,9 +314,9 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::PIXELFORMATDESCRIPTOR *ppfd
pfd = ppfd;
pfdID = id;
-
- canRGBA = pfd->iPixelType == PFD_TYPE_RGBA;
- canCI = pfd->iPixelType == PFD_TYPE_COLORINDEX;
+
+ canRGBA = pfd->iPixelType == PFD_TYPE_RGBA;
+ canCI = pfd->iPixelType == PFD_TYPE_COLORINDEX;
bufSize = pfd->cColorBits + pfd->cAlphaBits;
@@ -330,9 +345,11 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::PIXELFORMATDESCRIPTOR *ppfd
accB = pfd->cAccumBlueBits;
accA = pfd->cAccumAlphaBits;
- canWindow = pfd->dwFlags & PFD_DRAW_TO_WINDOW;
+ samples = 0; // XXX implement properly for Windows!
- canWinSysRender = pfd->dwFlags & PFD_SUPPORT_GDI;
+ canWindow = pfd->dwFlags & PFD_DRAW_TO_WINDOW;
+
+ canWinSysRender = pfd->dwFlags & PFD_SUPPORT_GDI;
if (pfd->dwFlags & PFD_GENERIC_FORMAT)
{
@@ -341,20 +358,20 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::PIXELFORMATDESCRIPTOR *ppfd
// it's an MCD - at least it has some acceleration
fast = true;
}
- else
+ else
{
- // it's software
+ // it's software
fast = false;
}
}
- else
+ else
{
- // it's an ICD
+ // it's an ICD
fast = true;
}
// we'll assume that the OpenGL implementation thinks it is conformant
- conformant = true;
+ conformant = true;
// chromakeying isn't supported
transparent = false;
@@ -379,15 +396,16 @@ DrawingSurfaceConfig::DrawingSurfaceConfig() {
accB = 32;
accA = 32;
+ samples = 0;
- canWindow = 1;
- canWinSysRender = 1;
+ canWindow = 1;
+ canWinSysRender = 1;
// This is a software-mode assumption
fast = false;
// we'll assume that the OpenGL implementation thinks it is conformant
- conformant = true;
+ conformant = true;
// chromakeying isn't supported
transparent = false;
@@ -399,18 +417,18 @@ DrawingSurfaceConfig::DrawingSurfaceConfig() {
DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::AGLPixelFormat pfd)
{
long i;
-
+
if (!mapsInitialized)
initializeMaps();
pf = pfd;
-
+
if (aglDescribePixelFormat( pf, AGL_RGBA, &i))
canRGBA = (i == GL_TRUE);
- canCI = (i == GL_FALSE);
+ canCI = (i == GL_FALSE);
if (aglDescribePixelFormat( pf, AGL_BUFFER_SIZE, &i))
- bufSize = i;
+ bufSize = i;
level = 0;
@@ -437,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);
@@ -453,7 +473,7 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(int id, ::AGLPixelFormat pfd)
fast = i;
// we'll assume that the OpenGL implementation thinks it is conformant
- conformant = true;
+ conformant = true;
// chromakeying isn't supported
transparent = false;
@@ -545,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;
@@ -628,7 +651,10 @@ DrawingSurfaceConfig::DrawingSurfaceConfig(string& str) {
string
DrawingSurfaceConfig::canonicalDescription() {
- ostringstream s;
+ // Would rather use ostringstream, but it's not available in
+ // egcs 1.1.2.
+ char buf[1024];
+ ostrstream s(buf, sizeof(buf));
# if defined(__X11__)
s << mapVarToName[VID] << ' ' << visID;
@@ -636,7 +662,7 @@ DrawingSurfaceConfig::canonicalDescription() {
s << ' ' << mapVarToName[VFBCID] << ' ' << fbcID;
# endif
# elif defined(__WIN__)
- s << mapVarToName[VID] << ' ' << pfdID;
+ s << mapVarToName[VID] << ' ' << pfdID;
# endif
s << ' ' << mapVarToName[VCANRGBA] << ' ' << canRGBA;
@@ -666,6 +692,8 @@ DrawingSurfaceConfig::canonicalDescription() {
<< ' ' << mapVarToName[VACCUMB] << ' ' << accB
<< ' ' << mapVarToName[VACCUMA] << ' ' << accA;
+ s << ' ' << mapVarToName[VSAMPLES] << ' ' << samples;
+
s << ' ' << mapVarToName[VCANWINDOW] << ' ' << canWindow;
# if defined(__X11__)
@@ -703,7 +731,8 @@ DrawingSurfaceConfig::canonicalDescription() {
///////////////////////////////////////////////////////////////////////////////
string
DrawingSurfaceConfig::conciseDescription() {
- ostringstream s;
+ char buf[1024];
+ ostrstream s(buf, sizeof(buf));
if (canRGBA && canCI)
s << "dual ";
@@ -765,6 +794,10 @@ DrawingSurfaceConfig::conciseDescription() {
}
}
+ if (samples) {
+ s << ", samples" << samples;
+ }
+
{
s << ", ";
bool sep = false;
@@ -865,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 a5f24f92..ea7ffd7c 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 e5cf32fa..6b1795b4 100644
--- a/tests/glean/dsfilt.cpp
+++ b/tests/glean/dsfilt.cpp
@@ -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
@@ -10,11 +12,11 @@
// 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
@@ -23,7 +25,7 @@
// 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
@@ -32,6 +34,7 @@
// dsfilt.cpp: Implementation of drawing surface configuration filtering
#include <iostream>
+#include <strstream>
#include <ctype.h>
#include <stdlib.h>
#include <algorithm>
@@ -213,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;
@@ -282,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;
@@ -302,7 +309,7 @@ DrawingSurfaceFilter::FetchVariable(const DrawingSurfaceConfig& c, Token v) {
# else
return 0;
# endif
-
+
case VAR_LEVEL:
return c.level;
case VAR_MAIN:
diff --git a/tests/glean/dsfilt.h b/tests/glean/dsfilt.h
index 89c6d583..ec715759 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/glutils.cpp b/tests/glean/glutils.cpp
index df19c8ca..ff3b0707 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 83942f4f..fd28f49c 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 adfdc224..17626701 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 492226a4..ec0ac47a 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 32eddd27..15fe59d4 100644
--- a/tests/glean/tapi2.cpp
+++ b/tests/glean/tapi2.cpp
@@ -1,7 +1,7 @@
// BEGIN_COPYRIGHT -*- glean -*-
-//
+//
// Copyright (C) 1999 Allen Akin 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
@@ -10,11 +10,11 @@
// 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
@@ -23,7 +23,7 @@
// 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
// tapi2.h: Test OpenGL 2.x API functions/features
@@ -31,11 +31,11 @@
#define GL_GLEXT_PROTOTYPES
-#include "tapi2.h"
-#include <cassert>
+#include <stdlib.h>
#include <cstring>
-#include <cstdlib>
-#include <cmath>
+#include <cassert>
+#include <math.h>
+#include "tapi2.h"
namespace GLEAN {
@@ -205,7 +205,7 @@ API2Test::setup(void)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDrawBuffer(GL_FRONT);
- glReadBuffer(GL_FRONT);
+ glReadBuffer(GL_FRONT);
// compute error tolerances (may need fine-tuning)
int bufferBits[5];
@@ -283,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);
}
@@ -321,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);
}
@@ -704,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;
}
@@ -750,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 f5950fb8..cd01fc94 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,
@@ -257,14 +266,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
@@ -280,8 +298,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
@@ -298,7 +321,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 3d87d6c0..be346578 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 110eb565..54e97df0 100644
--- a/tests/glean/tdepthstencil.cpp
+++ b/tests/glean/tdepthstencil.cpp
@@ -30,14 +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>
-#include <cstdlib>
-#include <cstring>
#ifdef GL_EXT_packed_depth_stencil
diff --git a/tests/glean/tfbo.cpp b/tests/glean/tfbo.cpp
index e269fead..325b523d 100644
--- a/tests/glean/tfbo.cpp
+++ b/tests/glean/tfbo.cpp
@@ -82,15 +82,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;
}
@@ -1218,7 +1224,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);
@@ -1239,15 +1246,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);
@@ -1268,15 +1276,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 +
@@ -1286,13 +1296,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);
@@ -1303,7 +1313,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 4a35c602..01d0d271 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 7a93eda1..2038007a 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 216dc506..9abe354c 100644
--- a/tests/glean/tfragprog1.cpp
+++ b/tests/glean/tfragprog1.cpp
@@ -437,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"
@@ -564,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 a98694ac..42bc9c4e 100644
--- a/tests/glean/tglsl1.cpp
+++ b/tests/glean/tglsl1.cpp
@@ -336,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",
@@ -1060,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"
@@ -1091,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 *=",
@@ -2898,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
};
@@ -3205,13 +3334,6 @@ 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";
- return false;
- }
-
// check GLSL version
#ifdef GL_SHADING_LANGUAGE_VERSION
const char *glslVersion = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
@@ -3222,7 +3344,7 @@ GLSLTest::setup(void)
env->log << "GLSL 1.x not supported\n";
return false;
}
- glsl_120 = (verString[2] >= '2');
+ glsl_120 = (glslVersion[2] >= '2');
if (!getFunctions()) {
env->log << "Unable to get pointer to an OpenGL 2.0 API function\n";
@@ -3662,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 cf1ed924..73972b0e 100644
--- a/tests/glean/tglsl1.h
+++ b/tests/glean/tglsl1.h
@@ -59,8 +59,11 @@ 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:
diff --git a/tests/glean/tlogicop.cpp b/tests/glean/tlogicop.cpp
index 5aee3520..470654a7 100644
--- a/tests/glean/tlogicop.cpp
+++ b/tests/glean/tlogicop.cpp
@@ -1,7 +1,7 @@
// BEGIN_COPYRIGHT -*- glean -*-
-//
+//
// Copyright (C) 1999 Allen Akin 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
@@ -10,11 +10,11 @@
// 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
@@ -23,22 +23,22 @@
// 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
// tlogicop.cpp: Test RGBA logic op functions.
// 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>
-#include <cstdlib>
namespace {
-struct logicopNameMapping {GLenum op; const char* name;};
+struct logicopNameMapping {GLenum op; char* name;};
logicopNameMapping logicopNames[] = {
{GL_CLEAR, "GL_CLEAR"},
{GL_SET, "GL_SET"},
@@ -58,7 +58,7 @@ logicopNameMapping logicopNames[] = {
{GL_OR_INVERTED, "GL_OR_INVERTED"}
};
-const char*
+char*
logicopToName(GLenum op) {
for (unsigned int i = 0;
i < sizeof(logicopNames) / sizeof(logicopNames[0]); ++i) {
@@ -90,7 +90,7 @@ makeRGBA(GLEAN::RandomBits& rRand,
rgba[3] = aRand.next() & 0xff;
} // makeRGBA
-void
+void
drawQuad(const int x, const int y, const GLubyte* color) {
glColor4ubv(color);
glBegin(GL_QUADS);
@@ -233,7 +233,7 @@ static runResult
runTest(GLenum logicop,
GLEAN::DrawingSurfaceConfig& config, GLEAN::Environment& env) {
using namespace GLEAN;
-
+
runResult result;
int y;
diff --git a/tests/glean/toccluqry.cpp b/tests/glean/toccluqry.cpp
index 2359bb6b..a362fc13 100644
--- a/tests/glean/toccluqry.cpp
+++ b/tests/glean/toccluqry.cpp
@@ -33,12 +33,12 @@
*/
#define GL_GLEXT_PROTOTYPES
-#include "toccluqry.h"
+#include <stdlib.h>
#include <cassert>
-#include <cstdlib>
-#include <cstdio>
#include <cstring>
+#include <stdio.h>
#include <cmath>
+#include "toccluqry.h"
#define START_QUERY(id)\
@@ -86,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 1683b4e7..7807a089 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"
#include <cstdlib>
diff --git a/tests/glean/tpbo.cpp b/tests/glean/tpbo.cpp
index 0b5e7c2e..5ae7a574 100644
--- a/tests/glean/tpbo.cpp
+++ b/tests/glean/tpbo.cpp
@@ -34,12 +34,15 @@
#define GL_GLEXT_PROTOTYPES
-#include "tpbo.h"
-#include <cassert>
-#include <cmath>
-#include <cstdlib>
+
+#include <stdlib.h>
#include <cstring>
+#include <cassert>
+#include <math.h>
+#include "tpbo.h"
#include "timer.h"
+
+
namespace GLEAN
{
@@ -81,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 1d367faf..3603bf57 100644
--- a/tests/glean/tpixelformats.cpp
+++ b/tests/glean/tpixelformats.cpp
@@ -1,7 +1,7 @@
// BEGIN_COPYRIGHT -*- glean -*-
-//
+//
// Copyright (C) 1999 Allen Akin 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
@@ -10,11 +10,11 @@
// 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
@@ -23,14 +23,14 @@
// 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
-#include "tpixelformats.h"
+#include <stdlib.h>
#include <cassert>
#include <cmath>
-#include <cstdlib>
+#include "tpixelformats.h"
// Set to 1 to help debug test failures:
@@ -1119,8 +1119,8 @@ PixelFormatsTest::ComputeExpected(GLenum srcFormat, int testChan,
exp[3] = testChan == 1 ? 255 : 0;
break;
case GL_RGB:
- exp[0] =
- exp[1] =
+ exp[0] =
+ exp[1] =
exp[2] = testChan == 0 ? 255 : 0;
exp[3] = defaultAlpha; // fragment alpha or texture alpha
break;
@@ -1131,8 +1131,8 @@ PixelFormatsTest::ComputeExpected(GLenum srcFormat, int testChan,
exp[3] = testChan == 1 ? 255 : 0;
break;
case GL_LUMINANCE:
- exp[0] =
- exp[1] =
+ exp[0] =
+ exp[1] =
exp[2] = testChan == 0 ? 255 : 0;
exp[3] = defaultAlpha; // fragment alpha or texture alpha
break;
@@ -1202,7 +1202,7 @@ PixelFormatsTest::CheckRendering(int width, int height, int comp,
sprintf(msg, " Expected: 0x%02x 0x%02x 0x%02x 0x%02x\n",
expected[0], expected[1], expected[2], expected[3]);
env->log << msg;
- sprintf(msg, " Found: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ sprintf(msg, " Found: 0x%02x 0x%02x 0x%02x 0x%02x\n",
image[i + 0], image[i + 1], image[i + 2], image[i + 3]);
env->log << msg;
ok = false;
diff --git a/tests/glean/tpointsprite.cpp b/tests/glean/tpointsprite.cpp
index c098d915..280984c2 100644
--- a/tests/glean/tpointsprite.cpp
+++ b/tests/glean/tpointsprite.cpp
@@ -40,12 +40,13 @@
*/
#define GL_GLEXT_PROTOTYPES
-#include "tpointsprite.h"
+
+#include <stdlib.h>
#include <cassert>
#include <cmath>
-#include <cstring>
-#include <cstdio>
-#include <cstdlib>
+#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 00000000..643bb621
--- /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 00000000..e1fc9c1d
--- /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 00000000..d0c783a8
--- /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 00000000..8c332cda
--- /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 00000000..1173d523
--- /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 00000000..f6d323ee
--- /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 9f593c49..930d6b73 100644
--- a/tests/glean/ttexenv.cpp
+++ b/tests/glean/ttexenv.cpp
@@ -40,11 +40,13 @@
// post-texture alpha value is correct.
//
-#include "ttexenv.h"
+#include <stdlib.h>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cmath>
+#include "ttexenv.h"
+
namespace GLEAN {
diff --git a/tests/glean/ttexswizzle.cpp b/tests/glean/ttexswizzle.cpp
new file mode 100644
index 00000000..6bd1304a
--- /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 00000000..efe39414
--- /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 b125976e..4fa5b9d1 100644
--- a/tests/glean/ttexture_srgb.cpp
+++ b/tests/glean/ttexture_srgb.cpp
@@ -30,11 +30,12 @@
// Brian Paul August 2006
-#include "ttexture_srgb.h"
-#include "rand.h"
#include <cassert>
-#include <cmath>
#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 00000000..e84c94e1
--- /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 00000000..803c515b
--- /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 00000000..737af0c4
--- /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 00000000..2b3a1184
--- /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 7338b8f2..6dadf904 100644
--- a/tests/glean/tvertattrib.cpp
+++ b/tests/glean/tvertattrib.cpp
@@ -45,14 +45,11 @@
// Author: Brian Paul (brian.paul a t tungstengraphics.com) October 2004
-#include <cmath>
-#ifdef __CYGWIN__
-#undef log2
-#endif
-#include <cstdlib>
+#include <stdlib.h>
+#include <cassert>
+#include <math.h>
#include "tvertattrib.h"
#include "glutils.h"
-#include <cassert>
namespace GLEAN {