2 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
23 * Measure glTex[Sub]Image2D() and glGetTexImage() rate
33 int WinWidth
= 100, WinHeight
= 100;
36 static GLuint TexObj
= 0;
37 static GLubyte
*TexImage
= NULL
;
38 static GLsizei TexSize
;
39 static GLenum TexIntFormat
, TexSrcFormat
, TexSrcType
;
41 static const GLboolean DrawPoint
= GL_TRUE
;
42 static const GLboolean TexSubImage4
= GL_FALSE
;
52 static const char *mode_name
[MODE_COUNT
] =
67 static const struct vertex vertices
[1] = {
68 { 0.0, 0.0, 0.5, 0.5 },
71 #define VOFFSET(F) ((void *) offsetof(struct vertex, F))
74 /** Called from test harness/main */
78 /* setup VBO w/ vertex data */
79 glGenBuffersARB(1, &VBO
);
80 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, VBO
);
81 glBufferDataARB(GL_ARRAY_BUFFER_ARB
,
82 sizeof(vertices
), vertices
, GL_STATIC_DRAW_ARB
);
83 glVertexPointer(2, GL_FLOAT
, sizeof(struct vertex
), VOFFSET(x
));
84 glTexCoordPointer(2, GL_FLOAT
, sizeof(struct vertex
), VOFFSET(s
));
85 glEnableClientState(GL_VERTEX_ARRAY
);
86 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
89 glGenTextures(1, &TexObj
);
90 glBindTexture(GL_TEXTURE_2D
, TexObj
);
91 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
92 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
93 glEnable(GL_TEXTURE_2D
);
100 CreateUploadTexImage2D(unsigned count
)
103 for (i
= 0; i
< count
; i
++) {
105 glDeleteTextures(1, &TexObj
);
107 glGenTextures(1, &TexObj
);
108 glBindTexture(GL_TEXTURE_2D
, TexObj
);
109 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
110 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
112 glTexImage2D(GL_TEXTURE_2D
, 0, TexIntFormat
,
114 TexSrcFormat
, TexSrcType
, TexImage
);
117 glDrawArrays(GL_POINTS
, 0, 1);
124 UploadTexImage2D(unsigned count
)
127 for (i
= 0; i
< count
; i
++) {
128 /* XXX is this equivalent to a glTexSubImage call since we're
129 * always specifying the same image size? That case isn't optimized
130 * in Mesa but may be optimized in other drivers. Note sure how
131 * much difference that might make.
133 glTexImage2D(GL_TEXTURE_2D
, 0, TexIntFormat
,
135 TexSrcFormat
, TexSrcType
, TexImage
);
137 glDrawArrays(GL_POINTS
, 0, 1);
144 UploadTexSubImage2D(unsigned count
)
147 for (i
= 0; i
< count
; i
++) {
149 GLsizei halfSize
= (TexSize
== 1) ? 1 : TexSize
/ 2;
150 GLsizei halfPos
= TexSize
- halfSize
;
151 /* do glTexSubImage2D in four pieces */
153 glPixelStorei(GL_UNPACK_ROW_LENGTH
, TexSize
);
154 glTexSubImage2D(GL_TEXTURE_2D
, 0,
155 0, 0, halfSize
, halfSize
,
156 TexSrcFormat
, TexSrcType
, TexImage
);
158 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, halfPos
);
159 glTexSubImage2D(GL_TEXTURE_2D
, 0,
160 halfPos
, 0, halfSize
, halfSize
,
161 TexSrcFormat
, TexSrcType
, TexImage
);
163 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, 0);
164 glPixelStorei(GL_UNPACK_SKIP_ROWS
, halfPos
);
165 glTexSubImage2D(GL_TEXTURE_2D
, 0,
166 0, halfPos
, halfSize
, halfSize
,
167 TexSrcFormat
, TexSrcType
, TexImage
);
169 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, halfPos
);
170 glPixelStorei(GL_UNPACK_SKIP_ROWS
, halfPos
);
171 glTexSubImage2D(GL_TEXTURE_2D
, 0,
172 halfPos
, halfPos
, halfSize
, halfSize
,
173 TexSrcFormat
, TexSrcType
, TexImage
);
174 /* reset the unpacking state */
175 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, 0);
176 glPixelStorei(GL_UNPACK_SKIP_ROWS
, 0);
177 glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
180 /* replace whole texture image at once */
181 glTexSubImage2D(GL_TEXTURE_2D
, 0,
182 0, 0, TexSize
, TexSize
,
183 TexSrcFormat
, TexSrcType
, TexImage
);
186 glDrawArrays(GL_POINTS
, 0, 1);
193 GetTexImage2D(unsigned count
)
196 GLubyte
*buf
= (GLubyte
*) malloc(TexSize
* TexSize
* 4);
197 for (i
= 0; i
< count
; i
++) {
198 glGetTexImage(GL_TEXTURE_2D
, 0,
199 TexSrcFormat
, TexSrcType
, buf
);
206 /* XXX any other formats to measure? */
207 static const struct {
209 GLenum internal_format
;
214 { GL_RGBA
, GL_UNSIGNED_BYTE
, GL_RGBA
, "RGBA/ubyte", 4, GL_TRUE
},
215 { GL_RGB
, GL_UNSIGNED_BYTE
, GL_RGB
, "RGB/ubyte", 3, GL_FALSE
},
216 { GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
, GL_RGB
, "RGB/565", 2, GL_FALSE
},
217 { GL_BGRA
, GL_UNSIGNED_BYTE
, GL_RGBA
, "BGRA/ubyte", 4, GL_FALSE
},
218 { GL_LUMINANCE
, GL_UNSIGNED_BYTE
, GL_LUMINANCE
, "L/ubyte", 1, GL_FALSE
},
219 { 0, 0, 0, NULL
, 0, 0 }
223 /** Called from test harness/main */
230 /** Called from test harness/main */
238 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &maxSize
);
240 /* loop over source data formats */
241 for (fmt
= 0; SrcFormats
[fmt
].format
; fmt
++) {
242 TexIntFormat
= SrcFormats
[fmt
].internal_format
;
243 TexSrcFormat
= SrcFormats
[fmt
].format
;
244 TexSrcType
= SrcFormats
[fmt
].type
;
246 /* loop over glTexImage, glTexSubImage */
247 for (mode
= 0; mode
< MODE_COUNT
; mode
++) {
250 if (SrcFormats
[fmt
].full_test
) {
256 if (mode
== MODE_CREATE_TEXIMAGE
)
260 /* loop over a defined range of texture sizes, test only the
261 * ones which are legal for this driver.
263 for (TexSize
= minsz
; TexSize
<= maxsz
; TexSize
*= 4) {
266 if (TexSize
<= maxSize
) {
269 bytesPerImage
= TexSize
* TexSize
* SrcFormats
[fmt
].texel_size
;
270 TexImage
= malloc(bytesPerImage
);
274 rate
= PerfMeasureRate(UploadTexImage2D
);
277 case MODE_CREATE_TEXIMAGE
:
278 rate
= PerfMeasureRate(CreateUploadTexImage2D
);
281 case MODE_TEXSUBIMAGE
:
282 /* create initial, empty texture */
283 glTexImage2D(GL_TEXTURE_2D
, 0, TexIntFormat
,
285 TexSrcFormat
, TexSrcType
, NULL
);
286 rate
= PerfMeasureRate(UploadTexSubImage2D
);
289 case MODE_GETTEXIMAGE
:
290 glTexImage2D(GL_TEXTURE_2D
, 0, TexIntFormat
,
292 TexSrcFormat
, TexSrcType
, TexImage
);
293 rate
= PerfMeasureRate(GetTexImage2D
);
300 mbPerSec
= rate
* bytesPerImage
/ (1024.0 * 1024.0);
308 perf_printf("non-zero glGetError() %d\n", err
);
319 perf_printf(" %s(%s %d x %d): "
320 "%.1f images/sec, %.1f MB/sec\n",
322 SrcFormats
[fmt
].name
, TexSize
, TexSize
, rate
, mbPerSec
);
325 if (SrcFormats
[fmt
].full_test
)