From 681ad9d1bb3616ce2ae1f695049d356cb6ce75dd Mon Sep 17 00:00:00 2001 From: Geoff Lang Date: Thu, 23 Apr 2015 12:27:56 -0400 Subject: [PATCH] Add a sample that uses multiple windows. BUG=angleproject:521 Change-Id: I50858193518b4d07edcb2073caaa99ce37fcc4c3 Reviewed-on: https://chromium-review.googlesource.com/267000 Reviewed-by: Brandon Jones Reviewed-by: Jamie Madill Tested-by: Geoff Lang --- samples/multi_window/MultiWindow.cpp | 186 +++++++++++++++++++++++++++ samples/samples.gyp | 8 ++ util/OSWindow.cpp | 18 ++- util/OSWindow.h | 5 + util/win32/Win32Window.cpp | 23 +++- util/win32/Win32Window.h | 1 + 6 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 samples/multi_window/MultiWindow.cpp diff --git a/samples/multi_window/MultiWindow.cpp b/samples/multi_window/MultiWindow.cpp new file mode 100644 index 000000000..7bf7b6f2b --- /dev/null +++ b/samples/multi_window/MultiWindow.cpp @@ -0,0 +1,186 @@ +// +// 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 "Matrix.h" +#include "SampleApplication.h" +#include "random_utils.h" +#include "shader_utils.h" + +#include +#include + +class MultiWindowSample : public SampleApplication +{ + public: + MultiWindowSample::MultiWindowSample() + : SampleApplication("MultiWindow", 256, 256) + { + } + + virtual bool initialize() + { + 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); + } + + for (size_t i = 1; i < mWindows.size(); i++) + { + int x = rootWindow.osWindow->getX() + static_cast(RandomBetween(0, 512)); + int y = rootWindow.osWindow->getY() + static_cast(RandomBetween(0, 512)); + int width = static_cast(RandomBetween(128, 512)); + int height = static_cast(RandomBetween(128, 512)); + mWindows[i].osWindow->setPosition(x, y); + mWindows[i].osWindow->resize(width, height); + } + + return true; + } + + virtual void destroy() + { + glDeleteProgram(mProgram); + } + + virtual void step(float dt, double totalTime) + { + mRotation = fmod(mRotation + (dt * 40.0f), 360.0f); + } + + virtual void draw() + { + 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 (size_t i = 1; i < mWindows.size(); i++) + { + OSWindow* window = mWindows[i].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 (size_t i = 0; i < mWindows.size(); i++) + { + OSWindow* window = mWindows[i].osWindow; + EGLSurface surface = mWindows[i].surface; + + eglMakeCurrent(getDisplay(), surface, surface, getContext()); + + Matrix4 orthoMatrix = Matrix4::ortho(static_cast(window->getX()), static_cast(window->getX() + window->getWidth()), + static_cast(window->getY() + window->getHeight()), static_cast(window->getY()), + 0.0f, 1.0f); + Matrix4 mvpMatrix = orthoMatrix * viewMatrix * modelMatrix; + + Vector3 vertices[] = + { + Matrix4::transform(mvpMatrix, Vector4(midX, static_cast(top), 0.0f, 1.0f)), + Matrix4::transform(mvpMatrix, Vector4(static_cast(left), static_cast(bottom), 0.0f, 1.0f)), + Matrix4::transform(mvpMatrix, Vector4(static_cast(right), static_cast(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); + } + } + + private: + // Handle to a program object + GLuint mProgram; + + // Current rotation + float mRotation; + + // Window and surface data + struct window + { + OSWindow* osWindow; + EGLSurface surface; + }; + std::vector mWindows; +}; + +int main(int argc, char **argv) +{ + MultiWindowSample app; + return app.run(); +} diff --git a/samples/samples.gyp b/samples/samples.gyp index a73695803..614ca5828 100644 --- a/samples/samples.gyp +++ b/samples/samples.gyp @@ -100,6 +100,14 @@ ] }, + { + 'target_name': 'multi_window', + 'type': 'executable', + 'dependencies': [ 'sample_util' ], + 'includes': [ '../build/common_defines.gypi', ], + 'sources': [ 'multi_window/MultiWindow.cpp', ], + }, + { 'target_name': 'multiple_draw_buffers', 'type': 'executable', diff --git a/util/OSWindow.cpp b/util/OSWindow.cpp index 06d920f21..a170bc69a 100644 --- a/util/OSWindow.cpp +++ b/util/OSWindow.cpp @@ -7,7 +7,9 @@ #include "OSWindow.h" OSWindow::OSWindow() - : mWidth(0), + : mX(0), + mY(0), + mWidth(0), mHeight(0) { } @@ -15,6 +17,16 @@ OSWindow::OSWindow() OSWindow::~OSWindow() {} +int OSWindow::getX() const +{ + return mX; +} + +int OSWindow::getY() const +{ + return mY; +} + int OSWindow::getWidth() const { return mWidth; @@ -43,6 +55,10 @@ void OSWindow::pushEvent(Event event) { switch (event.Type) { + case Event::EVENT_MOVED: + mX = event.Move.X; + mY = event.Move.Y; + break; case Event::EVENT_RESIZED: mWidth = event.Size.Width; mHeight = event.Size.Height; diff --git a/util/OSWindow.h b/util/OSWindow.h index 221c40387..0a688e3a2 100644 --- a/util/OSWindow.h +++ b/util/OSWindow.h @@ -22,6 +22,8 @@ class OSWindow virtual bool initialize(const std::string &name, size_t width, size_t height) = 0; virtual void destroy() = 0; + int getX() const; + int getY() const; int getWidth() const; int getHeight() const; @@ -34,6 +36,7 @@ class OSWindow virtual void pushEvent(Event event); virtual void setMousePosition(int x, int y) = 0; + virtual bool setPosition(int x, int y) = 0; virtual bool resize(int width, int height) = 0; virtual void setVisible(bool isVisible) = 0; @@ -43,6 +46,8 @@ class OSWindow bool didTestEventFire(); protected: + int mX; + int mY; int mWidth; int mHeight; diff --git a/util/win32/Win32Window.cpp b/util/win32/Win32Window.cpp index 88b8ad78c..b29124d16 100644 --- a/util/win32/Win32Window.cpp +++ b/util/win32/Win32Window.cpp @@ -518,6 +518,27 @@ OSWindow *CreateOSWindow() return new Win32Window(); } +bool Win32Window::setPosition(int x, int y) +{ + if (mX == x && mY == mY) + { + return true; + } + + RECT windowRect; + if (!GetWindowRect(mParentWindow, &windowRect)) + { + return false; + } + + if (!MoveWindow(mParentWindow, x, y, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, TRUE)) + { + return false; + } + + return true; +} + bool Win32Window::resize(int width, int height) { if (width == mWidth && height == mHeight) @@ -539,7 +560,7 @@ bool Win32Window::resize(int width, int height) LONG diffX = (windowRect.right - windowRect.left) - clientRect.right; LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom; - if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY, FALSE)) + if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY, TRUE)) { return false; } diff --git a/util/win32/Win32Window.h b/util/win32/Win32Window.h index a2ff03f54..81a4d118a 100644 --- a/util/win32/Win32Window.h +++ b/util/win32/Win32Window.h @@ -28,6 +28,7 @@ class Win32Window : public OSWindow void pushEvent(Event event) override; void setMousePosition(int x, int y) override; + bool setPosition(int x, int y) override; bool resize(int width, int height) override; void setVisible(bool isVisible) override;