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.
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
;
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.
45 g_display
= XOpenDisplay(NULL
);
47 std::cout
<< "Error - cannot open display" << std::endl
;
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
);
70 // Initialize the OpenGL context.
71 void InitGLContext() {
72 if (!InitializeGLBindings(gfx::kGLImplementationDesktopGL
)) {
73 LOG(ERROR
) << "InitializeGLBindings failed";
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
,
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
);
96 if (!glXMakeCurrent(g_display
, g_window
, g_gl_context
)) {
97 glXDestroyContext(g_display
, g_gl_context
);
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
) {
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
);
133 image
+= tile_size
* kStartSize
- kStartSize
;
137 void Render(int tile_size
) {
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.
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
++]);
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);
168 glDisableClientState(GL_VERTEX_ARRAY
);
169 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
171 glXSwapBuffers(g_display
, g_window
);
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.
181 start_time
= base::Time::Now().ToInternalValue();
184 UpdateTextures(tile_size
);
187 // We have finished rendering for this size, output the numbers.
189 base::TimeDelta delta
= base::Time::Now() -
190 base::Time::FromInternalValue(start_time
);
191 std::cout
<< "size = " << tile_size
192 << " speed = " << delta
.InMilliseconds()
195 tile_size
/= kSizeFactor
;
196 count
= kRenderCount
;
200 if (tile_size
<= kEndSize
) {
201 MessageLoop::current()->Quit();
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
)) {
216 XNextEvent(g_display
, &e
);
227 base::AtExitManager at_exit
;
233 loop
.PostTask(FROM_HERE
, base::Bind(&ProcessEvents
));
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
);