1/* 2 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 */ 21 22/** 23 * Measure glCopyTex[Sub]Image() rate. 24 * Create a large, off-screen framebuffer object for rendering and 25 * copying the texture data from it since we can't make really large 26 * on-screen windows. 27 * 28 * Brian Paul 29 * 22 Sep 2009 30 */ 31 32#include <string.h> 33#include "glmain.h" 34#include "common.h" 35 36int WinWidth = 100, WinHeight = 100; 37 38static GLuint VBO, FBO, RBO, Tex; 39 40const GLsizei MinSize = 16, MaxSize = 4096; 41static GLsizei TexSize; 42 43static const GLboolean DrawPoint = GL_TRUE; 44static const GLboolean TexSubImage4 = GL_FALSE; 45 46struct vertex 47{ 48 GLfloat x, y, s, t; 49}; 50 51static const struct vertex vertices[1] = { 52 { 0.0, 0.0, 0.5, 0.5 }, 53}; 54 55#define VOFFSET(F) ((void *) offsetof(struct vertex, F)) 56 57 58/** Called from test harness/main */ 59void 60PerfInit(void) 61{ 62 const GLenum filter = GL_LINEAR; 63 GLenum stat; 64 65 if (!PerfExtensionSupported("GL_EXT_framebuffer_object")) { 66 perf_printf("copytex: GL_EXT_framebuffer_object not supported\n"); 67 exit(0); 68 } 69 70 /* setup VBO */ 71 glGenBuffersARB(1, &VBO); 72 glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO); 73 glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices), 74 vertices, GL_STATIC_DRAW_ARB); 75 76 glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x)); 77 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s)); 78 glEnableClientState(GL_VERTEX_ARRAY); 79 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 80 81 /* setup texture */ 82 glGenTextures(1, &Tex); 83 glBindTexture(GL_TEXTURE_2D, Tex); 84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); 85 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); 86 glEnable(GL_TEXTURE_2D); 87 88 /* setup rbo */ 89 glGenRenderbuffersEXT(1, &RBO); 90 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBO); 91 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, MaxSize, MaxSize); 92 93 /* setup fbo */ 94 glGenFramebuffersEXT(1, &FBO); 95 glBindFramebufferEXT(GL_FRAMEBUFFER, FBO); 96 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 97 GL_COLOR_ATTACHMENT0_EXT, 98 GL_RENDERBUFFER_EXT, RBO); 99 100 stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 101 if (stat != GL_FRAMEBUFFER_COMPLETE_EXT) { 102 perf_printf("fboswitch: Error: incomplete FBO!\n"); 103 exit(1); 104 } 105 106 /* clear the FBO */ 107 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 108 glViewport(0, 0, MaxSize, MaxSize); 109 glClear(GL_COLOR_BUFFER_BIT); 110} 111 112 113static void 114CopyTexImage(unsigned count) 115{ 116 unsigned i; 117 for (i = 1; i < count; i++) { 118 /* draw something */ 119 if (DrawPoint) 120 glDrawArrays(GL_POINTS, 0, 1); 121 122 /* copy whole texture */ 123 glCopyTexImage2D(GL_TEXTURE_2D, 0, 124 GL_RGBA, 0, 0, TexSize, TexSize, 0); 125 } 126 glFinish(); 127} 128 129 130static void 131CopyTexSubImage(unsigned count) 132{ 133 unsigned i; 134 for (i = 1; i < count; i++) { 135 /* draw something */ 136 if (DrawPoint) 137 glDrawArrays(GL_POINTS, 0, 1); 138 139 /* copy sub texture */ 140 if (TexSubImage4) { 141 /* four sub-copies */ 142 GLsizei half = TexSize / 2; 143 /* lower-left */ 144 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 145 0, 0, 0, 0, half, half); 146 /* lower-right */ 147 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 148 half, 0, half, 0, half, half); 149 /* upper-left */ 150 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 151 0, half, 0, half, half, half); 152 /* upper-right */ 153 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 154 half, half, half, half, half, half); 155 } 156 else { 157 /* one big copy */ 158 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 159 0, 0, 0, 0, TexSize, TexSize); 160 } 161 } 162 glFinish(); 163} 164 165 166/** Called from test harness/main */ 167void 168PerfNextRound(void) 169{ 170} 171 172 173/** Called from test harness/main */ 174void 175PerfDraw(void) 176{ 177 double rate, mbPerSec; 178 GLint sub, maxTexSize; 179 180 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); 181 182 /* loop over whole/sub tex copy */ 183 for (sub = 0; sub < 2; sub++) { 184 185 /* loop over texture sizes */ 186 for (TexSize = MinSize; TexSize <= MaxSize; TexSize *= 4) { 187 188 if (TexSize <= maxTexSize) { 189 GLint bytesPerImage = 4 * TexSize * TexSize; 190 191 if (sub == 0) 192 rate = PerfMeasureRate(CopyTexImage); 193 else { 194 /* setup empty dest texture */ 195 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 196 TexSize, TexSize, 0, 197 GL_RGBA, GL_UNSIGNED_BYTE, NULL); 198 rate = PerfMeasureRate(CopyTexSubImage); 199 } 200 201 mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0); 202 } 203 else { 204 rate = 0.0; 205 mbPerSec = 0.0; 206 } 207 208 perf_printf(" glCopyTex%sImage(%d x %d): %.1f copies/sec, %.1f Mpixels/sec\n", 209 (sub ? "Sub" : ""), TexSize, TexSize, rate, mbPerSec); 210 } 211 } 212 213 exit(0); 214} 215