blob: 59d6eeed3ddb5c981ce46bc0858132dd410e39fc [file] [log] [blame]
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "SampleApplication.h"
#include <cmath>
#include <algorithm>
#include <vector>
#include "Matrix.h"
#include "random_utils.h"
#include "shader_utils.h"
using namespace angle;
class MultiWindowSample : public SampleApplication
{
public:
MultiWindowSample()
: SampleApplication("MultiWindow", 256, 256)
{
}
bool initialize() override
{
const std::string vs = SHADER_SOURCE
(
attribute vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
);
const std::string fs = SHADER_SOURCE
(
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
mProgram = CompileProgram(vs, fs);
if (!mProgram)
{
return false;
}
// Set an initial rotation
mRotation = 45.0f;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
window rootWindow;
rootWindow.osWindow = getWindow();
rootWindow.surface = getSurface();
mWindows.push_back(rootWindow);
const size_t numWindows = 5;
for (size_t i = 1; i < numWindows; i++)
{
window window;
window.osWindow = CreateOSWindow();
if (!window.osWindow->initialize("MultiWindow", 256, 256))
{
return false;
}
window.surface = eglCreateWindowSurface(getDisplay(), getConfig(), window.osWindow->getNativeWindow(), nullptr);
if (window.surface == EGL_NO_SURFACE)
{
return false;
}
window.osWindow->setVisible(true);
mWindows.push_back(window);
}
int baseX = rootWindow.osWindow->getX();
int baseY = rootWindow.osWindow->getY();
for (auto &window : mWindows)
{
int x = baseX + mRNG.randomIntBetween(0, 512);
int y = baseY + mRNG.randomIntBetween(0, 512);
int width = mRNG.randomIntBetween(128, 512);
int height = mRNG.randomIntBetween(128, 512);
window.osWindow->setPosition(x, y);
window.osWindow->resize(width, height);
}
return true;
}
void destroy() override { glDeleteProgram(mProgram); }
void step(float dt, double totalTime) override
{
mRotation = fmod(mRotation + (dt * 40.0f), 360.0f);
for (auto &window : mWindows)
{
window.osWindow->messageLoop();
}
}
void draw() override
{
OSWindow* rootWindow = mWindows[0].osWindow;
int left = rootWindow->getX();
int right = rootWindow->getX() + rootWindow->getWidth();
int top = rootWindow->getY();
int bottom = rootWindow->getY() + rootWindow->getHeight();
for (auto &windowRecord : mWindows)
{
OSWindow *window = windowRecord.osWindow;
left = std::min(left, window->getX());
right = std::max(right, window->getX() + window->getWidth());
top = std::min(top, window->getY());
bottom = std::max(bottom, window->getY() + window->getHeight());
}
float midX = (left + right) * 0.5f;
float midY = (top + bottom) * 0.5f;
Matrix4 modelMatrix = Matrix4::translate(Vector3(midX, midY, 0.0f)) *
Matrix4::rotate(mRotation, Vector3(0.0f, 0.0f, 1.0f)) *
Matrix4::translate(Vector3(-midX, -midY, 0.0f));
Matrix4 viewMatrix = Matrix4::identity();
for (auto &windowRecord : mWindows)
{
OSWindow *window = windowRecord.osWindow;
EGLSurface surface = windowRecord.surface;
eglMakeCurrent(getDisplay(), surface, surface, getContext());
Matrix4 orthoMatrix = Matrix4::ortho(static_cast<float>(window->getX()), static_cast<float>(window->getX() + window->getWidth()),
static_cast<float>(window->getY() + window->getHeight()), static_cast<float>(window->getY()),
0.0f, 1.0f);
Matrix4 mvpMatrix = orthoMatrix * viewMatrix * modelMatrix;
Vector3 vertices[] =
{
Matrix4::transform(mvpMatrix, Vector4(midX, static_cast<float>(top), 0.0f, 1.0f)),
Matrix4::transform(mvpMatrix, Vector4(static_cast<float>(left), static_cast<float>(bottom), 0.0f, 1.0f)),
Matrix4::transform(mvpMatrix, Vector4(static_cast<float>(right), static_cast<float>(bottom), 0.0f, 1.0f)),
};
// Set the viewport
glViewport(0, 0, window->getWidth(), window->getHeight());
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(mProgram);
// Load the vertex data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices[0].data());
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
eglSwapBuffers(getDisplay(), surface);
}
}
// Override swap to do nothing as we already swapped the root
// window in draw() and swapping another time would invalidate
// the content of the default framebuffer.
void swap() override {}
private:
// Handle to a program object
GLuint mProgram;
// Current rotation
float mRotation;
// Window and surface data
struct window
{
OSWindow* osWindow;
EGLSurface surface;
};
std::vector<window> mWindows;
RNG mRNG;
};
int main(int argc, char **argv)
{
MultiWindowSample app;
return app.run();
}