| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Android window. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuAndroidWindow.hpp" |
| |
| namespace tcu |
| { |
| namespace Android |
| { |
| |
| using std::vector; |
| |
| // Window |
| |
| Window::Window (ANativeWindow* window) |
| : m_window (window) |
| , m_state (STATE_AVAILABLE) |
| { |
| } |
| |
| Window::~Window (void) |
| { |
| } |
| |
| void Window::setBuffersGeometry (int width, int height, int32_t format) |
| { |
| ANativeWindow_setBuffersGeometry(m_window, width, height, format); |
| } |
| |
| IVec2 Window::getSize (void) const |
| { |
| const int32_t width = ANativeWindow_getWidth(m_window); |
| const int32_t height = ANativeWindow_getHeight(m_window); |
| return IVec2(width, height); |
| } |
| |
| bool Window::tryAcquire (void) |
| { |
| de::ScopedLock lock(m_stateLock); |
| |
| if (m_state == STATE_AVAILABLE) |
| { |
| m_state = STATE_IN_USE; |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| void Window::release (void) |
| { |
| de::ScopedLock lock(m_stateLock); |
| |
| if (m_state == STATE_IN_USE) |
| { |
| // Reset buffer size and format back to initial state |
| ANativeWindow_setBuffersGeometry(m_window, 0, 0, 0); |
| |
| m_state = STATE_AVAILABLE; |
| } |
| else if (m_state == STATE_PENDING_DESTROY) |
| m_state = STATE_READY_FOR_DESTROY; |
| else |
| DE_FATAL("Invalid window state"); |
| } |
| |
| void Window::markForDestroy (void) |
| { |
| de::ScopedLock lock(m_stateLock); |
| |
| if (m_state == STATE_AVAILABLE) |
| m_state = STATE_READY_FOR_DESTROY; |
| else if (m_state == STATE_IN_USE) |
| m_state = STATE_PENDING_DESTROY; |
| else |
| DE_FATAL("Invalid window state"); |
| } |
| |
| bool Window::isPendingDestroy (void) const |
| { |
| de::ScopedLock lock(m_stateLock); |
| return m_state == STATE_PENDING_DESTROY; |
| } |
| |
| bool Window::tryAcquireForDestroy (bool onlyMarked) |
| { |
| de::ScopedLock lock(m_stateLock); |
| |
| if (m_state == STATE_READY_FOR_DESTROY || |
| (!onlyMarked && m_state == STATE_AVAILABLE)) |
| { |
| m_state = STATE_ACQUIRED_FOR_DESTROY; |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| // WindowRegistry |
| |
| WindowRegistry::WindowRegistry (void) |
| { |
| } |
| |
| WindowRegistry::~WindowRegistry (void) |
| { |
| for (vector<Window*>::const_iterator winIter = m_windows.begin(); winIter != m_windows.end(); winIter++) |
| { |
| Window* const window = *winIter; |
| |
| if (window->tryAcquireForDestroy(false)) |
| delete window; |
| else |
| { |
| print("ERROR: Window was not available for deletion, leaked tcu::Android::Window!\n"); |
| DE_FATAL("Window leaked"); |
| } |
| } |
| } |
| |
| void WindowRegistry::addWindow (ANativeWindow* window) |
| { |
| m_windows.reserve(m_windows.size()+1); |
| m_windows.push_back(new Window(window)); |
| } |
| |
| void WindowRegistry::destroyWindow (ANativeWindow* rawHandle) |
| { |
| for (int ndx = 0; ndx < (int)m_windows.size(); ++ndx) |
| { |
| Window* const window = m_windows[ndx]; |
| |
| if (window->getNativeWindow() == rawHandle) |
| { |
| if (window->tryAcquireForDestroy(false)) |
| { |
| delete window; |
| m_windows[ndx] = m_windows.back(); |
| m_windows.pop_back(); |
| } |
| else |
| window->markForDestroy(); |
| |
| return; |
| } |
| } |
| |
| throw tcu::InternalError("Window not registered", DE_NULL, __FILE__, __LINE__); |
| } |
| |
| Window* WindowRegistry::tryAcquireWindow (void) |
| { |
| for (int ndx = 0; ndx < (int)m_windows.size(); ++ndx) |
| { |
| Window* const window = m_windows[ndx]; |
| |
| if (window->tryAcquire()) |
| return window; |
| } |
| |
| return DE_NULL; |
| } |
| |
| void WindowRegistry::garbageCollect (void) |
| { |
| for (int ndx = 0; ndx < (int)m_windows.size(); ++ndx) |
| { |
| Window* const window = m_windows[ndx]; |
| |
| if (window->tryAcquireForDestroy(true)) |
| { |
| delete window; |
| m_windows[ndx] = m_windows.back(); |
| m_windows.pop_back(); |
| ndx -= 1; |
| } |
| } |
| } |
| |
| } // Android |
| } // tcu |