Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / tbufferobject.cpp
blob6ab2ea2a2d64ebd6fe58d6c3b9097b57c92929ec
1 // BEGIN_COPYRIGHT -*- glean -*-
2 //
3 // Copyright (C) 2009 VMware, Inc. All Rights Reserved.
4 //
5 // Permission is hereby granted, free of charge, to any person
6 // obtaining a copy of this software and associated documentation
7 // files (the "Software"), to deal in the Software without
8 // restriction, including without limitation the rights to use,
9 // copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following
12 // conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
16 // Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19 // KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL VMWARE BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 // DEALINGS IN THE SOFTWARE.
26 //
27 // END_COPYRIGHT
29 // tbufferobject.c - test various buffer object features/extensions
30 // Author: Brian Paul
33 #define GL_GLEXT_PROTOTYPES
34 #include <cassert>
35 #include <cmath>
36 #include <cstring>
37 #include <stdlib.h>
38 #include "tbufferobject.h"
41 namespace GLEAN {
44 // GL_ARB_vertex/fragment_program
45 static PFNGLGENBUFFERSARBPROC glGenBuffersARB_func = NULL;
46 static PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB_func = NULL;
47 static PFNGLBINDBUFFERARBPROC glBindBufferARB_func = NULL;
48 static PFNGLBUFFERDATAARBPROC glBufferDataARB_func = NULL;
49 static PFNGLMAPBUFFERARBPROC glMapBufferARB_func = NULL;
50 static PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB_func = NULL;
52 // GL_ARB_copy_buffer
53 static PFNGLCOPYBUFFERSUBDATAPROC glCopyBufferSubData_func = NULL;
55 // GL_ARB_map_buffer_range
56 static PFNGLMAPBUFFERRANGEPROC glMapBufferRange_func = NULL;
57 static PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange_func = NULL;
60 BufferObjectResult::BufferObjectResult()
62 pass = false;
66 bool
67 BufferObjectTest::setup(void)
69 have_ARB_vertex_buffer_object = GLUtils::haveExtension("GL_ARB_vertex_buffer_object");
70 have_ARB_pixel_buffer_object = GLUtils::haveExtension("GL_ARB_pixel_buffer_object");
71 have_ARB_copy_buffer = GLUtils::haveExtension("GL_ARB_copy_buffer");
72 have_ARB_map_buffer_range = GLUtils::haveExtension("GL_ARB_map_buffer_range");
74 if (have_ARB_vertex_buffer_object) {
75 target1 = GL_ARRAY_BUFFER_ARB;
76 target2 = GL_ELEMENT_ARRAY_BUFFER_ARB;
78 else if (have_ARB_pixel_buffer_object) {
79 target1 = GL_PIXEL_PACK_BUFFER_ARB;
80 target2 = GL_PIXEL_UNPACK_BUFFER_ARB;
82 else {
83 return false;
87 glGenBuffersARB_func = (PFNGLGENBUFFERSARBPROC) GLUtils::getProcAddress("glGenBuffersARB");
88 glDeleteBuffersARB_func = (PFNGLDELETEBUFFERSARBPROC) GLUtils::getProcAddress("glDeleteBuffersARB");
89 glBindBufferARB_func = (PFNGLBINDBUFFERARBPROC) GLUtils::getProcAddress("glBindBufferARB");
90 glBufferDataARB_func = (PFNGLBUFFERDATAARBPROC) GLUtils::getProcAddress("glBufferDataARB");
91 glMapBufferARB_func = (PFNGLMAPBUFFERARBPROC) GLUtils::getProcAddress("glMapBufferARB");
92 glUnmapBufferARB_func = (PFNGLUNMAPBUFFERARBPROC) GLUtils::getProcAddress("glUnmapBufferARB");
94 if (have_ARB_copy_buffer) {
95 glCopyBufferSubData_func = (PFNGLCOPYBUFFERSUBDATAPROC) GLUtils::getProcAddress("glCopyBufferSubData");
98 if (have_ARB_map_buffer_range) {
99 glMapBufferRange_func = (PFNGLMAPBUFFERRANGEPROC) GLUtils::getProcAddress("glMapBufferRange");
100 glFlushMappedBufferRange_func = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLUtils::getProcAddress("glFlushMappedBufferRange");
103 return true;
107 // test GL_ARB_copy_buffer
108 bool
109 BufferObjectTest::testCopyBuffer(void)
111 static const GLsizei size1 = 4200, size2 = 3800;
112 GLubyte buf1[size1], buf2[size2];
113 GLuint bufs[2];
114 GLubyte *map;
115 GLint i;
116 bool pass;
118 glGenBuffersARB_func(2, bufs);
120 // setup first buffer
121 glBindBufferARB_func(target1, bufs[0]);
122 glBufferDataARB_func(target1, size1, NULL, GL_STATIC_DRAW);
123 map = (GLubyte *) glMapBufferARB_func(target1, GL_WRITE_ONLY_ARB);
124 for (i = 0; i < size1; i++) {
125 map[i] = buf1[i] = i & 0xff;
127 glUnmapBufferARB_func(target1);
129 // setup second buffer
130 glBindBufferARB_func(target2, bufs[1]);
131 glBufferDataARB_func(target2, size2, NULL, GL_STATIC_DRAW);
132 map = (GLubyte *) glMapBufferARB_func(target2, GL_WRITE_ONLY_ARB);
133 for (i = 0; i < size2; i++) {
134 map[i] = buf2[i] = 0;
136 glUnmapBufferARB_func(target2);
138 // copy random sections of first buffer to second buffer
139 for (i = 0; i < 50; i++) {
140 const int min = size1 < size2 ? size1 : size2;
141 int size = rand.next() % min;
142 int srcOffset = rand.next() % (size1 - size);
143 int dstOffset = rand.next() % (size2 - size);
145 assert(srcOffset + size <= size1);
146 assert(dstOffset + size <= size2);
148 // test copy from first buffer to second
149 glCopyBufferSubData_func(target1, // src target
150 target2, // dst target
151 srcOffset, // src start
152 dstOffset, // dst start
153 size);
155 // update the validation/reference buffer in the same way
156 memcpy(buf2 + dstOffset, buf1 + srcOffset, size);
159 // no errors should have been generated.
160 if (glGetError()) {
161 env->log << "Unexpected GL error in copy buffer test.\n";
162 return false;
165 // check results in second buffer object
166 map = (GLubyte *) glMapBufferARB_func(target2, GL_READ_ONLY_ARB);
167 pass = true;
168 for (i = 0; i < size2; i++) {
169 if (map[i] != buf2[i]) {
170 printf("%d: %d != %d\n", i, map[i], buf2[i]);
171 pass = false;
172 break;
175 glUnmapBufferARB_func(target2);
177 glDeleteBuffersARB_func(2, bufs);
179 return pass;
183 // Test GL_ARB_map_buffer_range
184 // This isn't exhaustive, but covers the basics.
185 bool
186 BufferObjectTest::testMapBufferRange(void)
188 static const GLsizei size = 30000;
189 GLubyte buf[size];
190 GLuint buffer;
191 GLubyte *map;
192 GLint i, j;
193 bool pass = true;
195 // create buffer
196 glGenBuffersARB_func(1, &buffer);
197 glBindBufferARB_func(target1, buffer);
198 glBufferDataARB_func(target1, size, NULL, GL_STATIC_DRAW);
200 // initialize to zeros
201 map = (GLubyte *) glMapBufferRange_func(target1, 0, size, GL_MAP_WRITE_BIT);
202 for (i = 0; i < size; i++) {
203 map[i] = buf[i] = 0;
205 glUnmapBufferARB_func(target1);
207 // write to random ranges
208 for (i = 0; i < 50; i++) {
209 const int mapSize = rand.next() % size;
210 const int mapOffset = rand.next() % (size - mapSize);
212 assert(mapOffset + mapSize <= size);
214 map = (GLubyte *)
215 glMapBufferRange_func(target1, mapOffset, mapSize,
216 GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
218 for (j = 0; j < mapSize; j++) {
219 map[j] = buf[mapOffset + j] = (mapOffset + j) & 0xff;
222 glFlushMappedBufferRange_func(target1, 0, mapSize);
224 glUnmapBufferARB_func(target1);
227 if (glGetError())
228 pass = false;
230 // read/check random ranges
231 for (i = 0; i < 50 && pass; i++) {
232 const int mapSize = rand.next() % size;
233 const int mapOffset = rand.next() % (size - mapSize);
235 assert(mapOffset + mapSize <= size);
237 map = (GLubyte *) glMapBufferRange_func(target1, mapOffset,
238 mapSize, GL_MAP_READ_BIT);
240 for (j = 0; j < mapSize; j++) {
241 if (map[j] != buf[mapOffset + j]) {
242 pass = false;
243 break;
246 glUnmapBufferARB_func(target1);
249 glDeleteBuffersARB_func(1, &buffer);
251 if (glGetError())
252 pass = false;
254 return pass;
258 void
259 BufferObjectTest::runOne(BufferObjectResult &r, Window &w)
261 (void) w; // silence warning
262 r.pass = true;
264 if (!setup()) {
265 // if neither GL_ARB_vertex/pixel_buffer_object are supported, do nothing
266 r.pass = true;
267 return;
270 if (r.pass && have_ARB_copy_buffer)
271 r.pass = testCopyBuffer();
273 if (r.pass && have_ARB_map_buffer_range)
274 r.pass = testMapBufferRange();
278 void
279 BufferObjectTest::logOne(BufferObjectResult &r)
281 logPassFail(r);
282 logConcise(r);
286 void
287 BufferObjectTest::compareOne(BufferObjectResult &oldR,
288 BufferObjectResult &newR)
290 comparePassFail(oldR, newR);
294 void
295 BufferObjectResult::putresults(ostream &s) const
297 if (pass) {
298 s << "PASS\n";
300 else {
301 s << "FAIL\n";
306 bool
307 BufferObjectResult::getresults(istream &s)
309 char result[1000];
310 s >> result;
312 if (strcmp(result, "FAIL") == 0) {
313 pass = false;
315 else {
316 pass = true;
318 return s.good();
322 // The test object itself:
323 BufferObjectTest bufferObjectTest("bufferObject",
324 "window, rgb",
325 "", // no extension tests
326 "Test buffer object features and extensions such as:\n"
327 " GL_ARB_vertex_buffer_object\n"
328 " GL_ARB_pixel_buffer_object\n"
329 " GL_ARB_copy_buffer\n"
330 " GL_ARB_map_buffer_range\n");
334 } // namespace GLEAN