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