2 * OpenGL ES 2.0 memory performance estimator
3 * Copyright (C) 2009 Nokia
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * \author Sami Kyöstilä <sami.kyostila@nokia.com>
21 * CPU texture streaming test
23 #include "cpuinterleavingtest.h"
28 #include <X11/Xutil.h>
29 #include <X11/extensions/XShm.h>
33 template <typename TYPE>
34 void fillTexture(TYPE* pixels, int width, int height, int stride, int frame)
36 TYPE color = (TYPE)0xffffffffu;
37 for (int y = 0; y < height; y++)
39 for (int x = 0; x < width; x++)
41 if ((x + y + frame) & 0x10)
50 pixels += stride / sizeof(TYPE);
54 CPUInterleavingTest::CPUInterleavingTest(CPUInterleavingMethod method,
55 int buffers, int bitsPerPixel,
56 int width, int height,
57 float texW, float texH):
58 BlitTest(width, height, false, texW, texH),
61 m_dataBitsPerPixel(bitsPerPixel),
62 m_readBuffer(buffers - 1),
68 void CPUInterleavingTest::prepare()
75 glGenTextures(m_buffers, m_textures);
76 for (int i = 0; i < m_buffers; i++)
78 glBindTexture(GL_TEXTURE_2D, m_textures[i]);
79 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
80 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
87 case CPUI_TEXTURE_UPLOAD:
89 m_dataStride = m_width * m_dataBitsPerPixel / 8;
90 for (i = 0; i < m_buffers; i++)
92 m_textureData[i] = new char[m_height * m_dataStride];
98 Status shmSupported = XShmQueryExtension(ctx.nativeDisplay);
101 fail("X11 shared memory extension not supported");
104 m_completionEvent = XShmGetEventBase(ctx.nativeDisplay) + ShmCompletion;
106 const EGLint pixmapConfigAttrs[] =
108 EGL_BUFFER_SIZE, m_dataBitsPerPixel,
111 EGLint configCount = 0;
113 eglChooseConfig(ctx.dpy, pixmapConfigAttrs, &m_config, 1, &configCount);
116 for (i = 0; i < m_buffers; i++)
118 success = nativeCreatePixmap(ctx.nativeDisplay, ctx.dpy,
119 m_config, m_width, m_height, &m_pixmaps[i]);
123 m_gc[i] = XCreateGC(ctx.nativeDisplay, m_pixmaps[i], 0, &gcValues);
125 const EGLint surfAttrs[] =
127 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
128 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
129 EGL_MIPMAP_TEXTURE, EGL_FALSE,
133 m_surfaces[i] = eglCreatePixmapSurface(ctx.dpy, m_config, m_pixmaps[i], surfAttrs);
134 assert(m_surfaces[i] != EGL_NO_SURFACE);
136 glBindTexture(GL_TEXTURE_2D, m_textures[i]);
137 success = eglBindTexImage(ctx.dpy, m_surfaces[i], EGL_BACK_BUFFER);
140 XVisualInfo visualInfo;
143 visualInfo.depth = m_dataBitsPerPixel;
144 visualInfo.screen = DefaultScreen(ctx.nativeDisplay);
145 visual = XGetVisualInfo(ctx.nativeDisplay, VisualDepthMask | VisualScreenMask,
146 &visualInfo, &visualCount);
148 assert(visualCount > 0);
150 m_ximage[i] = XShmCreateImage(ctx.nativeDisplay, visual->visual, m_dataBitsPerPixel,
152 &m_shminfo[i], m_width, m_height);
153 m_shminfo[i].shmid = shmget(IPC_PRIVATE,
154 m_ximage[i]->bytes_per_line *
155 m_ximage[i]->height, IPC_CREAT | 0777);
156 m_shminfo[i].shmaddr = m_ximage[i]->data = (char*)shmat(m_shminfo[i].shmid, 0, 0);
157 assert(m_shminfo[i].shmaddr);
158 m_shminfo[i].readOnly = False;
159 Status status = XShmAttach(ctx.nativeDisplay, &m_shminfo[i]);
162 m_textureData[i] = m_ximage[i]->data;
163 m_dataStride = m_ximage[i]->bytes_per_line;
164 m_writeCompleted[i] = true;
165 m_drawableIndex[m_pixmaps[i]] = i;
175 void CPUInterleavingTest::teardown()
178 glDeleteTextures(m_buffers, m_textures);
182 case CPUI_TEXTURE_UPLOAD:
184 for (i = 0; i < m_buffers; i++)
186 delete[] m_textureData[i];
190 case CPUI_XSHM_IMAGE:
192 for (i = 0; i < m_buffers; i++)
194 XShmDetach(ctx.nativeDisplay, &m_shminfo[i]);
195 XDestroyImage(m_ximage[i]);
196 shmdt(m_shminfo[i].shmaddr);
197 shmctl(m_shminfo[i].shmid, IPC_RMID, 0);
199 eglReleaseTexImage(ctx.dpy, m_surfaces[i], EGL_BACK_BUFFER);
200 eglDestroySurface(ctx.dpy, m_surfaces[i]);
201 nativeDestroyPixmap(ctx.nativeDisplay, m_pixmaps[i]);
202 XFreeGC(ctx.nativeDisplay, m_gc[i]);
211 BlitTest::teardown();
214 std::string CPUInterleavingTest::name() const
222 case CPUI_TEXTURE_UPLOAD:
225 case CPUI_XSHM_IMAGE:
228 case CPUI_IMG_TEXTURE_STREAMING:
231 case CPUI_PIXEL_BUFFER_OBJECT:
234 case CPUI_EGL_LOCK_SURFACE:
239 switch (m_dataBitsPerPixel)
249 s << "_" << m_buffers << "x" << m_width << "x" << m_height;
254 void CPUInterleavingTest::operator()(int frame)
256 switch (m_dataBitsPerPixel)
259 fillTexture(reinterpret_cast<uint16_t*>(m_textureData[m_writeBuffer]),
260 m_width, m_height, m_dataStride, frame);
263 fillTexture(reinterpret_cast<uint32_t*>(m_textureData[m_writeBuffer]),
264 m_width, m_height, m_dataStride, frame);
268 glBindTexture(GL_TEXTURE_2D, m_textures[m_writeBuffer]);
272 case CPUI_TEXTURE_UPLOAD:
273 if (m_dataBitsPerPixel == 32)
275 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0,
276 GL_RGBA, GL_UNSIGNED_BYTE, m_textureData[m_writeBuffer]);
280 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0,
281 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, m_textureData[m_writeBuffer]);
284 case CPUI_XSHM_IMAGE:
286 // Wait for the completion event for this buffer
287 while (XEventsQueued(ctx.nativeDisplay, QueuedAfterReading) > 0 ||
288 !m_writeCompleted[m_writeBuffer])
291 XNextEvent(ctx.nativeDisplay, &event);
292 if (event.type == m_completionEvent)
294 XShmCompletionEvent* e = reinterpret_cast<XShmCompletionEvent*>(&event);
295 int i = m_drawableIndex[e->drawable];
296 m_writeCompleted[i] = true;
299 XShmPutImage(ctx.nativeDisplay, m_pixmaps[m_writeBuffer], m_gc[m_writeBuffer],
300 m_ximage[m_writeBuffer], 0, 0, 0, 0, m_width, m_height, True);
301 m_writeCompleted[m_writeBuffer] = false;
309 glBindTexture(GL_TEXTURE_2D, m_textures[m_readBuffer]);
310 m_writeBuffer = (m_writeBuffer + 1) % m_buffers;
311 m_readBuffer = (m_readBuffer + 1) % m_buffers;
313 BlitTest::operator()(frame);