Mailbox support for texture layers.
[chromium-blink-merge.git] / media / tools / tile_render_bench / tile_render_bench.cc
blobd5b7e2908f21b863079548b035299d6bc56e3542
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This tool is used to benchmark the technique of using tiles to render a
6 // large tecture. This tool runs with different tile sizes so that developer
7 // can determine the right dimensions for the tiles.
9 #include <iostream>
11 #include <X11/Xlib.h>
12 #include <X11/Xutil.h>
13 #include <X11/keysym.h>
15 #include "base/at_exit.h"
16 #include "base/basictypes.h"
17 #include "base/bind.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/message_loop.h"
20 #include "ui/gl/gl_bindings.h"
21 #include "ui/gl/gl_implementation.h"
23 // Initial size of the window and the texture.
24 static const int kStartSize = 1024;
26 // The smallest texture size we're trying.
27 static const int kEndSize = 16;
29 // Factor for dividing the size from one step to another.
30 static const int kSizeFactor = 2;
32 // Number of renders before we output.
33 static const int kRenderCount = 1000;
34 static const int kMaxTextures = kStartSize * kStartSize / kEndSize / kEndSize;
36 Display* g_display = NULL;
37 Window g_window = 0;
38 GLXContext g_gl_context = NULL;
39 GLuint g_textures[kMaxTextures];
40 scoped_array<uint8> g_image;
42 // Initialize X11. Returns true if successful. This method creates the X11
43 // window. Further initialization is done in X11VideoRenderer.
44 bool InitX11() {
45 g_display = XOpenDisplay(NULL);
46 if (!g_display) {
47 std::cout << "Error - cannot open display" << std::endl;
48 return false;
51 // Get properties of the screen.
52 int screen = DefaultScreen(g_display);
53 int root_window = RootWindow(g_display, screen);
55 // Creates the window.
56 g_window = XCreateSimpleWindow(g_display, root_window, 1, 1, 100, 50, 0,
57 BlackPixel(g_display, screen),
58 BlackPixel(g_display, screen));
59 XStoreName(g_display, g_window, "Tile Render Bench");
61 XSelectInput(g_display, g_window,
62 ExposureMask | ButtonPressMask | KeyPressMask);
63 XMapWindow(g_display, g_window);
65 XResizeWindow(g_display, g_window, kStartSize, kStartSize);
67 return true;
70 // Initialize the OpenGL context.
71 void InitGLContext() {
72 if (!InitializeGLBindings(gfx::kGLImplementationDesktopGL)) {
73 LOG(ERROR) << "InitializeGLBindings failed";
74 return;
77 XWindowAttributes attributes;
78 XGetWindowAttributes(g_display, g_window, &attributes);
79 XVisualInfo visual_info_template;
80 visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
81 int visual_info_count = 0;
82 XVisualInfo* visual_info_list = XGetVisualInfo(g_display, VisualIDMask,
83 &visual_info_template,
84 &visual_info_count);
86 for (int i = 0; i < visual_info_count && !g_gl_context; ++i) {
87 g_gl_context = glXCreateContext(g_display, visual_info_list + i, 0,
88 True /* Direct rendering */);
91 XFree(visual_info_list);
92 if (!g_gl_context) {
93 return;
96 if (!glXMakeCurrent(g_display, g_window, g_gl_context)) {
97 glXDestroyContext(g_display, g_gl_context);
98 g_gl_context = NULL;
99 return;
103 void InitTest() {
104 g_image.reset(new uint8[kStartSize * kStartSize]);
105 for (int i = 0; i < kStartSize; ++i) {
106 for (int j = 0; j < kStartSize; ++j) {
107 bool white = (i / 16) % 2 == (j / 16) % 2;
108 g_image.get()[i * kStartSize + j] = white ? 255 : 0;
112 glGenTextures(kMaxTextures, g_textures);
113 for (int i = 0; i < kMaxTextures; ++i) {
114 glBindTexture(GL_TEXTURE_2D, g_textures[i]);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
118 glEnable(GL_TEXTURE_2D);
121 void UpdateTextures(int tile_size) {
122 int k = 0;
123 uint8* image = g_image.get();
124 for (int y = 0; y < kStartSize; y += tile_size) {
125 for (int x = 0; x < kStartSize; x += tile_size) {
126 glBindTexture(GL_TEXTURE_2D, g_textures[k]);
127 glPixelStorei(GL_UNPACK_ROW_LENGTH, kStartSize);
128 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, tile_size, tile_size, 0,
129 GL_LUMINANCE, GL_UNSIGNED_BYTE, image);
130 ++k;
131 image += tile_size;
133 image += tile_size * kStartSize - kStartSize;
137 void Render(int tile_size) {
138 float points[] ={
139 0, 0, 0,
140 1, 0, 0,
141 1, 1, 0,
142 0, 1, 0
144 GLfloat tex_coords[] = {0, 0, 1, 0, 1, 1, 0, 1};
146 glEnableClientState(GL_VERTEX_ARRAY);
147 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
149 glVertexPointer(3, GL_FLOAT, 0, points);
150 glTexCoordPointer(2, GL_FLOAT, 0, tex_coords);
152 // This will tile them from bottom-up. I'm too lazy to think about top-down.
153 int k = 0;
154 int scale_factor = kStartSize / tile_size;
155 double step = 1 / scale_factor;
156 for (int y = 0; y < kStartSize; y += tile_size) {
157 for (int x = 0; x < kStartSize; x += tile_size) {
158 glBindTexture(GL_TEXTURE_2D, g_textures[k++]);
159 glPushMatrix();
160 glTranslated(-1, -1, 0);
161 glScaled(2.0 / scale_factor, 2.0 / scale_factor, 0);
162 glTranslated(x / tile_size * step, y / tile_size * step, 0);
163 glDrawArrays(GL_QUADS, 0, 4);
164 glPopMatrix();
168 glDisableClientState(GL_VERTEX_ARRAY);
169 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
171 glXSwapBuffers(g_display, g_window);
174 void RunTest() {
175 static int tile_size = kStartSize;
176 static int count = kRenderCount;
177 static int64 start_time = 0;
179 // If this is 0 that means this is the first time we render for this size.
180 if (!start_time) {
181 start_time = base::Time::Now().ToInternalValue();
184 UpdateTextures(tile_size);
185 Render(tile_size);
187 // We have finished rendering for this size, output the numbers.
188 if (--count == 0) {
189 base::TimeDelta delta = base::Time::Now() -
190 base::Time::FromInternalValue(start_time);
191 std::cout << "size = " << tile_size
192 << " speed = " << delta.InMilliseconds()
193 << std::endl;
194 std::cout.flush();
195 tile_size /= kSizeFactor;
196 count = kRenderCount;
197 start_time = 0;
200 if (tile_size <= kEndSize) {
201 MessageLoop::current()->Quit();
202 return;
205 XExposeEvent ev = { Expose, 0, 1, g_display, g_window,
206 0, 0, kStartSize, kStartSize, 0 };
207 XSendEvent(g_display, g_window, False, ExposureMask, (XEvent*)&ev);
209 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&RunTest));
212 void ProcessEvents() {
213 // Consume all the X events
214 while (XPending(g_display)) {
215 XEvent e;
216 XNextEvent(g_display, &e);
217 switch (e.type) {
218 case Expose:
219 RunTest();
220 default:
221 break;
226 int main() {
227 base::AtExitManager at_exit;
228 MessageLoop loop;
229 InitX11();
230 InitGLContext();
231 InitTest();
233 loop.PostTask(FROM_HERE, base::Bind(&ProcessEvents));
234 loop.Run();
236 // Cleanup GL.
237 glXMakeCurrent(g_display, 0, NULL);
238 glXDestroyContext(g_display, g_gl_context);
240 // Destroy window and display.
241 XDestroyWindow(g_display, g_window);
242 XCloseDisplay(g_display);
243 return 0;