1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "SampleApplication.h"
8
9 #include <algorithm>
10 #include <cmath>
11 #include <vector>
12
13 #include "util/Matrix.h"
14 #include "util/random_utils.h"
15 #include "util/shader_utils.h"
16
17 using namespace angle;
18
19 class MultiWindowSample : public SampleApplication
20 {
21 public:
MultiWindowSample(int argc,char ** argv)22 MultiWindowSample(int argc, char **argv)
23 : SampleApplication("MultiWindow", argc, argv, 2, 0, 256, 256)
24 {}
25
initialize()26 bool initialize() override
27 {
28 constexpr char kVS[] = R"(attribute vec4 vPosition;
29 void main()
30 {
31 gl_Position = vPosition;
32 })";
33
34 constexpr char kFS[] = R"(precision mediump float;
35 void main()
36 {
37 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
38 })";
39
40 mProgram = CompileProgram(kVS, kFS);
41 if (!mProgram)
42 {
43 return false;
44 }
45
46 // Set an initial rotation
47 mRotation = 45.0f;
48
49 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
50
51 window rootWindow;
52 rootWindow.osWindow = getWindow();
53 rootWindow.surface = getSurface();
54 mWindows.push_back(rootWindow);
55
56 const size_t numWindows = 5;
57 for (size_t i = 1; i < numWindows; i++)
58 {
59 window window;
60
61 window.osWindow = OSWindow::New();
62 if (!window.osWindow->initialize("MultiWindow", 256, 256))
63 {
64 return false;
65 }
66
67 window.surface = eglCreateWindowSurface(getDisplay(), getConfig(),
68 window.osWindow->getNativeWindow(), nullptr);
69 if (window.surface == EGL_NO_SURFACE)
70 {
71 return false;
72 }
73
74 window.osWindow->setVisible(true);
75
76 mWindows.push_back(window);
77 }
78
79 int baseX = rootWindow.osWindow->getX();
80 int baseY = rootWindow.osWindow->getY();
81 for (auto &window : mWindows)
82 {
83 int x = baseX + mRNG.randomIntBetween(0, 512);
84 int y = baseY + mRNG.randomIntBetween(0, 512);
85 int width = mRNG.randomIntBetween(128, 512);
86 int height = mRNG.randomIntBetween(128, 512);
87 window.osWindow->setPosition(x, y);
88 window.osWindow->resize(width, height);
89 }
90
91 return true;
92 }
93
destroy()94 void destroy() override { glDeleteProgram(mProgram); }
95
step(float dt,double totalTime)96 void step(float dt, double totalTime) override
97 {
98 mRotation = fmod(mRotation + (dt * 40.0f), 360.0f);
99
100 for (auto &window : mWindows)
101 {
102 window.osWindow->messageLoop();
103 }
104 }
105
draw()106 void draw() override
107 {
108 OSWindow *rootWindow = mWindows[0].osWindow;
109 int left = rootWindow->getX();
110 int right = rootWindow->getX() + rootWindow->getWidth();
111 int top = rootWindow->getY();
112 int bottom = rootWindow->getY() + rootWindow->getHeight();
113
114 for (auto &windowRecord : mWindows)
115 {
116 OSWindow *window = windowRecord.osWindow;
117 left = std::min(left, window->getX());
118 right = std::max(right, window->getX() + window->getWidth());
119 top = std::min(top, window->getY());
120 bottom = std::max(bottom, window->getY() + window->getHeight());
121 }
122
123 float midX = (left + right) * 0.5f;
124 float midY = (top + bottom) * 0.5f;
125
126 Matrix4 modelMatrix = Matrix4::translate(Vector3(midX, midY, 0.0f)) *
127 Matrix4::rotate(mRotation, Vector3(0.0f, 0.0f, 1.0f)) *
128 Matrix4::translate(Vector3(-midX, -midY, 0.0f));
129 Matrix4 viewMatrix = Matrix4::identity();
130
131 for (auto &windowRecord : mWindows)
132 {
133 OSWindow *window = windowRecord.osWindow;
134 EGLSurface surface = windowRecord.surface;
135
136 eglMakeCurrent(getDisplay(), surface, surface, getContext());
137
138 Matrix4 orthoMatrix =
139 Matrix4::ortho(static_cast<float>(window->getX()),
140 static_cast<float>(window->getX() + window->getWidth()),
141 static_cast<float>(window->getY() + window->getHeight()),
142 static_cast<float>(window->getY()), 0.0f, 1.0f);
143 Matrix4 mvpMatrix = orthoMatrix * viewMatrix * modelMatrix;
144
145 Vector3 vertices[] = {
146 Matrix4::transform(mvpMatrix, Vector4(midX, static_cast<float>(top), 0.0f, 1.0f)),
147 Matrix4::transform(mvpMatrix, Vector4(static_cast<float>(left),
148 static_cast<float>(bottom), 0.0f, 1.0f)),
149 Matrix4::transform(mvpMatrix, Vector4(static_cast<float>(right),
150 static_cast<float>(bottom), 0.0f, 1.0f)),
151 };
152
153 // Set the viewport
154 glViewport(0, 0, window->getWidth(), window->getHeight());
155
156 // Clear the color buffer
157 glClear(GL_COLOR_BUFFER_BIT);
158
159 // Use the program object
160 glUseProgram(mProgram);
161
162 // Load the vertex data
163 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices[0].data());
164 glEnableVertexAttribArray(0);
165
166 glDrawArrays(GL_TRIANGLES, 0, 3);
167
168 eglSwapBuffers(getDisplay(), surface);
169 }
170 }
171
172 // Override swap to do nothing as we already swapped the root
173 // window in draw() and swapping another time would invalidate
174 // the content of the default framebuffer.
swap()175 void swap() override {}
176
177 private:
178 // Handle to a program object
179 GLuint mProgram;
180
181 // Current rotation
182 float mRotation;
183
184 // Window and surface data
185 struct window
186 {
187 OSWindow *osWindow;
188 EGLSurface surface;
189 };
190 std::vector<window> mWindows;
191
192 RNG mRNG;
193 };
194
main(int argc,char ** argv)195 int main(int argc, char **argv)
196 {
197 MultiWindowSample app(argc, argv);
198 return app.run();
199 }
200