132001f49Smrg/*
232001f49Smrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
332001f49Smrg *
432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
532001f49Smrg * copy of this software and associated documentation files (the "Software"),
632001f49Smrg * to deal in the Software without restriction, including without limitation
732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
932001f49Smrg * Software is furnished to do so, subject to the following conditions:
1032001f49Smrg *
1132001f49Smrg * The above copyright notice and this permission notice shall be included
1232001f49Smrg * in all copies or substantial portions of the Software.
1332001f49Smrg *
1432001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1532001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1632001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1732001f49Smrg * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1832001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1932001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2032001f49Smrg */
2132001f49Smrg
2232001f49Smrg/**
2332001f49Smrg * Measure glCopyTex[Sub]Image() rate.
2432001f49Smrg * Create a large, off-screen framebuffer object for rendering and
2532001f49Smrg * copying the texture data from it since we can't make really large
2632001f49Smrg * on-screen windows.
2732001f49Smrg *
2832001f49Smrg * Brian Paul
2932001f49Smrg * 22 Sep 2009
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg#include <string.h>
3332001f49Smrg#include "glmain.h"
3432001f49Smrg#include "common.h"
3532001f49Smrg
3632001f49Smrgint WinWidth = 100, WinHeight = 100;
3732001f49Smrg
3832001f49Smrgstatic GLuint VBO, FBO, RBO, Tex;
3932001f49Smrg
4032001f49Smrgconst GLsizei MinSize = 16, MaxSize = 4096;
4132001f49Smrgstatic GLsizei TexSize;
4232001f49Smrg
4332001f49Smrgstatic const GLboolean DrawPoint = GL_TRUE;
4432001f49Smrgstatic const GLboolean TexSubImage4 = GL_FALSE;
4532001f49Smrg
4632001f49Smrgstruct vertex
4732001f49Smrg{
4832001f49Smrg   GLfloat x, y, s, t;
4932001f49Smrg};
5032001f49Smrg
5132001f49Smrgstatic const struct vertex vertices[1] = {
5232001f49Smrg   { 0.0, 0.0, 0.5, 0.5 },
5332001f49Smrg};
5432001f49Smrg
5532001f49Smrg#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
5632001f49Smrg
5732001f49Smrg
5832001f49Smrg/** Called from test harness/main */
5932001f49Smrgvoid
6032001f49SmrgPerfInit(void)
6132001f49Smrg{
6232001f49Smrg   const GLenum filter = GL_LINEAR;
6332001f49Smrg   GLenum stat;
6432001f49Smrg
6532001f49Smrg   if (!PerfExtensionSupported("GL_EXT_framebuffer_object")) {
6632001f49Smrg      perf_printf("copytex: GL_EXT_framebuffer_object not supported\n");
6732001f49Smrg      exit(0);
6832001f49Smrg   }
6932001f49Smrg
7032001f49Smrg   /* setup VBO */
7132001f49Smrg   glGenBuffersARB(1, &VBO);
7232001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
7332001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices),
7432001f49Smrg                   vertices, GL_STATIC_DRAW_ARB);
7532001f49Smrg
7632001f49Smrg   glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
7732001f49Smrg   glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
7832001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
7932001f49Smrg   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
8032001f49Smrg
8132001f49Smrg   /* setup texture */
8232001f49Smrg   glGenTextures(1, &Tex);
8332001f49Smrg   glBindTexture(GL_TEXTURE_2D, Tex);
8432001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
8532001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
8632001f49Smrg   glEnable(GL_TEXTURE_2D);
8732001f49Smrg
8832001f49Smrg   /* setup rbo */
8932001f49Smrg   glGenRenderbuffersEXT(1, &RBO);
9032001f49Smrg   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBO);
9132001f49Smrg   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, MaxSize, MaxSize);
9232001f49Smrg
9332001f49Smrg   /* setup fbo */
9432001f49Smrg   glGenFramebuffersEXT(1, &FBO);
9532001f49Smrg   glBindFramebufferEXT(GL_FRAMEBUFFER, FBO);
9632001f49Smrg   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
9732001f49Smrg                                GL_COLOR_ATTACHMENT0_EXT,
9832001f49Smrg                                GL_RENDERBUFFER_EXT, RBO);
9932001f49Smrg
10032001f49Smrg   stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
10132001f49Smrg   if (stat != GL_FRAMEBUFFER_COMPLETE_EXT) {
10232001f49Smrg      perf_printf("fboswitch: Error: incomplete FBO!\n");
10332001f49Smrg      exit(1);
10432001f49Smrg   }
10532001f49Smrg
10632001f49Smrg   /* clear the FBO */
10732001f49Smrg   glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
10832001f49Smrg   glViewport(0, 0, MaxSize, MaxSize);
10932001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
11032001f49Smrg}
11132001f49Smrg
11232001f49Smrg
11332001f49Smrgstatic void
11432001f49SmrgCopyTexImage(unsigned count)
11532001f49Smrg{
11632001f49Smrg   unsigned i;
11732001f49Smrg   for (i = 1; i < count; i++) {
11832001f49Smrg      /* draw something */
11932001f49Smrg      if (DrawPoint)
12032001f49Smrg         glDrawArrays(GL_POINTS, 0, 1);
12132001f49Smrg
12232001f49Smrg      /* copy whole texture */
12332001f49Smrg      glCopyTexImage2D(GL_TEXTURE_2D, 0,
12432001f49Smrg                       GL_RGBA, 0, 0, TexSize, TexSize, 0);
12532001f49Smrg   }
12632001f49Smrg   glFinish();
12732001f49Smrg}
12832001f49Smrg
12932001f49Smrg
13032001f49Smrgstatic void
13132001f49SmrgCopyTexSubImage(unsigned count)
13232001f49Smrg{
13332001f49Smrg   unsigned i;
13432001f49Smrg   for (i = 1; i < count; i++) {
13532001f49Smrg      /* draw something */
13632001f49Smrg      if (DrawPoint)
13732001f49Smrg         glDrawArrays(GL_POINTS, 0, 1);
13832001f49Smrg
13932001f49Smrg      /* copy sub texture */
14032001f49Smrg      if (TexSubImage4) {
14132001f49Smrg         /* four sub-copies */
14232001f49Smrg         GLsizei half = TexSize / 2;
14332001f49Smrg         /* lower-left */
14432001f49Smrg         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
14532001f49Smrg                             0, 0, 0, 0, half, half);
14632001f49Smrg         /* lower-right */
14732001f49Smrg         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
14832001f49Smrg                             half, 0, half, 0, half, half);
14932001f49Smrg         /* upper-left */
15032001f49Smrg         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
15132001f49Smrg                             0, half, 0, half, half, half);
15232001f49Smrg         /* upper-right */
15332001f49Smrg         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
15432001f49Smrg                             half, half, half, half, half, half);
15532001f49Smrg      }
15632001f49Smrg      else {
15732001f49Smrg         /* one big copy */
15832001f49Smrg         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
15932001f49Smrg                             0, 0, 0, 0, TexSize, TexSize);
16032001f49Smrg      }
16132001f49Smrg   }
16232001f49Smrg   glFinish();
16332001f49Smrg}
16432001f49Smrg
16532001f49Smrg
16632001f49Smrg/** Called from test harness/main */
16732001f49Smrgvoid
16832001f49SmrgPerfNextRound(void)
16932001f49Smrg{
17032001f49Smrg}
17132001f49Smrg
17232001f49Smrg
17332001f49Smrg/** Called from test harness/main */
17432001f49Smrgvoid
17532001f49SmrgPerfDraw(void)
17632001f49Smrg{
17732001f49Smrg   double rate, mbPerSec;
17832001f49Smrg   GLint sub, maxTexSize;
17932001f49Smrg
18032001f49Smrg   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
18132001f49Smrg
18232001f49Smrg   /* loop over whole/sub tex copy */
18332001f49Smrg   for (sub = 0; sub < 2; sub++) {
18432001f49Smrg
18532001f49Smrg      /* loop over texture sizes */
18632001f49Smrg      for (TexSize = MinSize; TexSize <= MaxSize; TexSize *= 4) {
18732001f49Smrg
18832001f49Smrg         if (TexSize <= maxTexSize) {
18932001f49Smrg            GLint bytesPerImage = 4 * TexSize * TexSize;
19032001f49Smrg
19132001f49Smrg            if (sub == 0)
19232001f49Smrg               rate = PerfMeasureRate(CopyTexImage);
19332001f49Smrg            else {
19432001f49Smrg               /* setup empty dest texture */
19532001f49Smrg               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
19632001f49Smrg                            TexSize, TexSize, 0,
19732001f49Smrg                            GL_RGBA, GL_UNSIGNED_BYTE, NULL);
19832001f49Smrg               rate = PerfMeasureRate(CopyTexSubImage);
19932001f49Smrg            }
20032001f49Smrg
20132001f49Smrg            mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
20232001f49Smrg         }
20332001f49Smrg         else {
20432001f49Smrg            rate = 0.0;
20532001f49Smrg            mbPerSec = 0.0;
20632001f49Smrg         }
20732001f49Smrg
20832001f49Smrg         perf_printf("  glCopyTex%sImage(%d x %d): %.1f copies/sec, %.1f Mpixels/sec\n",
20932001f49Smrg                     (sub ? "Sub" : ""), TexSize, TexSize, rate, mbPerSec);
21032001f49Smrg      }
21132001f49Smrg   }
21232001f49Smrg
21332001f49Smrg   exit(0);
21432001f49Smrg}
215