Commit ce991cf6 by Corentin Wallez

Add OSWindow::takeScreenshot to be used by some dEQP egl tests

This helps make dEQP support platform agnostic BUG=angleproject:892 Change-Id: Ifd9436caa8c79018a053c27e32b514ef9ebee707 Reviewed-on: https://chromium-review.googlesource.com/273596Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 3c85635d
......@@ -127,8 +127,6 @@ class NativeWindow : public eglu::NativeWindow
private:
OSWindow *mWindow;
eglu::WindowParams::Visibility mCurVisibility;
deUint64 mSetVisibleTime; //!< Time window was set visible.
EventState *mEvents;
};
......@@ -233,8 +231,6 @@ eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay* nativ
NativeWindow::NativeWindow(ANGLENativeDisplay *nativeDisplay, const eglu::WindowParams& params, EventState *eventState)
: eglu::NativeWindow(WINDOW_CAPABILITIES),
mWindow(CreateOSWindow()),
mCurVisibility(eglu::WindowParams::VISIBILITY_HIDDEN),
mSetVisibleTime(0),
mEvents(eventState)
{
bool initialized = mWindow->initialize("dEQP ANGLE Tests",
......@@ -252,15 +248,12 @@ void NativeWindow::setVisibility(eglu::WindowParams::Visibility visibility)
{
case eglu::WindowParams::VISIBILITY_HIDDEN:
mWindow->setVisible(false);
mCurVisibility = visibility;
break;
case eglu::WindowParams::VISIBILITY_VISIBLE:
case eglu::WindowParams::VISIBILITY_FULLSCREEN:
// \todo [2014-03-12 pyry] Implement FULLSCREEN, or at least SW_MAXIMIZE.
mWindow->setVisible(true);
mCurVisibility = eglu::WindowParams::VISIBILITY_VISIBLE;
mSetVisibleTime = deGetMicroseconds();
break;
default:
......@@ -300,96 +293,10 @@ void NativeWindow::setSurfaceSize(IVec2 size)
void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const
{
HDC windowDC = DE_NULL;
HDC screenDC = DE_NULL;
HDC tmpDC = DE_NULL;
HBITMAP tmpBitmap = DE_NULL;
RECT rect;
TCU_CHECK_INTERNAL(mCurVisibility != eglu::WindowParams::VISIBILITY_HIDDEN);
// Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait
// for a while before issuing screenshot if window was just made visible.
{
const deInt64 timeSinceVisibleUs = (deInt64)(deGetMicroseconds()-mSetVisibleTime);
if (timeSinceVisibleUs < (deInt64)WAIT_WINDOW_VISIBLE_MS*1000)
deSleep(WAIT_WINDOW_VISIBLE_MS - (deUint32)(timeSinceVisibleUs/1000));
}
TCU_CHECK(GetClientRect(mWindow->getNativeWindow(), &rect));
try
{
const int width = rect.right - rect.left;
const int height = rect.bottom - rect.top;
BITMAPINFOHEADER bitmapInfo;
deMemset(&bitmapInfo, 0, sizeof(bitmapInfo));
screenDC = GetDC(DE_NULL);
TCU_CHECK(screenDC);
windowDC = GetDC(mWindow->getNativeWindow());
TCU_CHECK(windowDC);
tmpDC = CreateCompatibleDC(screenDC);
TCU_CHECK(tmpDC != DE_NULL);
MapWindowPoints(mWindow->getNativeWindow() , DE_NULL, (LPPOINT)&rect, 2);
tmpBitmap = CreateCompatibleBitmap(screenDC, width, height);
TCU_CHECK(tmpBitmap != DE_NULL);
TCU_CHECK(SelectObject(tmpDC, tmpBitmap) != DE_NULL);
TCU_CHECK(BitBlt(tmpDC, 0, 0, width, height, screenDC, rect.left, rect.top, SRCCOPY));
bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.biWidth = width;
bitmapInfo.biHeight = -height;
bitmapInfo.biPlanes = 1;
bitmapInfo.biBitCount = 32;
bitmapInfo.biCompression = BI_RGB;
bitmapInfo.biSizeImage = 0;
bitmapInfo.biXPelsPerMeter = 0;
bitmapInfo.biYPelsPerMeter = 0;
bitmapInfo.biClrUsed = 0;
bitmapInfo.biClrImportant = 0;
dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8), width, height);
TCU_CHECK(GetDIBits(screenDC, tmpBitmap, 0, height, dst->getAccess().getDataPtr(), (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS));
DeleteObject(tmpBitmap);
tmpBitmap = DE_NULL;
ReleaseDC(DE_NULL, screenDC);
screenDC = DE_NULL;
ReleaseDC(mWindow->getNativeWindow(), windowDC);
windowDC = DE_NULL;
DeleteDC(tmpDC);
tmpDC = DE_NULL;
}
catch (...)
{
if (screenDC)
ReleaseDC(DE_NULL, screenDC);
if (windowDC)
ReleaseDC(mWindow->getNativeWindow(), windowDC);
if (tmpBitmap)
DeleteObject(tmpBitmap);
if (tmpDC)
DeleteDC(tmpDC);
throw;
}
dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8), mWindow->getWidth(), mWindow->getHeight());
bool success = mWindow->takeScreenshot(reinterpret_cast<uint8_t*>(dst->getAccess().getDataPtr()));
DE_ASSERT(success);
DE_UNREF(success);
}
} // anonymous
......
......@@ -11,6 +11,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <cstdint>
#include <list>
#include <string>
......@@ -28,6 +29,12 @@ class OSWindow
int getWidth() const;
int getHeight() const;
// Takes a screenshot of the window, returning the result as a mWidth * mHeight * 4
// normalized unsigned byte BGRA array. Note that it will be used to test the window
// manager's behavior so it needs to take an actual screenshot of the screen and not
// just grab the pixels of the window. Returns if it was successful.
virtual bool takeScreenshot(uint8_t *pixelData) { return false; }
virtual EGLNativeWindowType getNativeWindow() const = 0;
virtual EGLNativeDisplayType getNativeDisplay() const = 0;
......
......@@ -10,6 +10,8 @@
#include <sstream>
#include "common/debug.h"
Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags)
{
switch (key)
......@@ -374,7 +376,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
Win32Window::Win32Window()
: mNativeWindow(0),
: mIsVisible(false),
mSetVisibleTimer(CreateTimer()),
mNativeWindow(0),
mParentWindow(0),
mNativeDisplay(0)
{
......@@ -383,6 +387,7 @@ Win32Window::Win32Window()
Win32Window::~Win32Window()
{
destroy();
delete mSetVisibleTimer;
}
bool Win32Window::initialize(const std::string &name, size_t width, size_t height)
......@@ -482,6 +487,108 @@ void Win32Window::destroy()
UnregisterClassA(mChildClassName.c_str(), NULL);
}
bool Win32Window::takeScreenshot(uint8_t *pixelData)
{
if (mIsVisible)
{
return false;
}
bool error = false;
// Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait
// for a while before issuing screenshot if window was just made visible.
{
static const double WAIT_WINDOW_VISIBLE_MS = 0.5; // Half a second for the animation
double timeSinceVisible = mSetVisibleTimer->getElapsedTime();
if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS)
{
Sleep(static_cast<DWORD>((WAIT_WINDOW_VISIBLE_MS - timeSinceVisible) * 1000));
}
}
HDC screenDC = nullptr;
HDC windowDC = nullptr;
HDC tmpDC = nullptr;
HBITMAP tmpBitmap = nullptr;
if (!error)
{
screenDC = GetDC(nullptr);
error = screenDC == nullptr;
}
if (!error)
{
windowDC = GetDC(mNativeWindow);
error = windowDC == nullptr;
}
if (!error)
{
tmpDC = CreateCompatibleDC(screenDC);
error = tmpDC == nullptr;
}
if (!error)
{
tmpBitmap = CreateCompatibleBitmap(screenDC, mWidth, mHeight);
error = tmpBitmap == nullptr;
}
RECT rect = {0, 0, 0, 0};
if (!error)
{
MapWindowPoints(mNativeWindow, nullptr, reinterpret_cast<LPPOINT>(&rect), 0);
error = SelectObject(tmpDC, tmpBitmap) == nullptr;
}
if (!error)
{
error = BitBlt(tmpDC, 0, 0, mWidth, mHeight, screenDC, rect.left, rect.top, SRCCOPY) == TRUE;
}
if (!error)
{
BITMAPINFOHEADER bitmapInfo;
bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.biWidth = mWidth;
bitmapInfo.biHeight = -mHeight;
bitmapInfo.biPlanes = 1;
bitmapInfo.biBitCount = 32;
bitmapInfo.biCompression = BI_RGB;
bitmapInfo.biSizeImage = 0;
bitmapInfo.biXPelsPerMeter = 0;
bitmapInfo.biYPelsPerMeter = 0;
bitmapInfo.biClrUsed = 0;
bitmapInfo.biClrImportant = 0;
int getBitsResult = GetDIBits(screenDC, tmpBitmap, 0, mHeight, pixelData,
reinterpret_cast<BITMAPINFO*>(&bitmapInfo), DIB_RGB_COLORS);
error = getBitsResult != 0;
}
if (tmpBitmap != nullptr)
{
DeleteObject(tmpBitmap);
}
if (tmpDC != nullptr)
{
DeleteDC(tmpDC);
}
if (screenDC != nullptr)
{
ReleaseDC(nullptr, screenDC);
}
if (windowDC != nullptr)
{
ReleaseDC(mNativeWindow, windowDC);
}
return !error;
}
EGLNativeWindowType Win32Window::getNativeWindow() const
{
return mNativeWindow;
......@@ -581,6 +688,12 @@ void Win32Window::setVisible(bool isVisible)
ShowWindow(mParentWindow, flag);
ShowWindow(mNativeWindow, flag);
if (isVisible)
{
mSetVisibleTimer->stop();
mSetVisibleTimer->start();
}
}
void Win32Window::pushEvent(Event event)
......
......@@ -13,6 +13,7 @@
#include <string>
#include "OSWindow.h"
#include "Timer.h"
class Win32Window : public OSWindow
{
......@@ -23,6 +24,8 @@ class Win32Window : public OSWindow
bool initialize(const std::string &name, size_t width, size_t height) override;
void destroy() override;
bool takeScreenshot(uint8_t *pixelData) override;
EGLNativeWindowType getNativeWindow() const override;
EGLNativeDisplayType getNativeDisplay() const override;
......@@ -41,6 +44,9 @@ class Win32Window : public OSWindow
std::string mParentClassName;
std::string mChildClassName;
bool mIsVisible;
Timer *mSetVisibleTimer;
EGLNativeWindowType mNativeWindow;
EGLNativeWindowType mParentWindow;
EGLNativeDisplayType mNativeDisplay;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment