/*------------------------------------------------------------------------- * drawElements Quality Program EGL Module * --------------------------------------- * * 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-specific operations. *//*--------------------------------------------------------------------*/ #include "teglAndroidUtil.hpp" #include "deStringUtil.hpp" #include "tcuTextureUtil.hpp" #include "gluTextureUtil.hpp" #include "glwEnums.hpp" #include "eglwLibrary.hpp" #include "eglwEnums.hpp" #if (DE_OS == DE_OS_ANDROID) # include "tcuAndroidInternals.hpp" #endif namespace deqp { namespace egl { namespace Image { using std::string; using de::MovePtr; using tcu::PixelBufferAccess; using tcu::TextureFormat; using tcu::Texture2D; using eglu::AttribMap; using namespace glw; using namespace eglw; #if (DE_OS != DE_OS_ANDROID) MovePtr<ImageSource> createAndroidNativeImageSource (GLenum format) { return createUnsupportedImageSource("Not Android platform", format); } #else // DE_OS == DE_OS_ANDROID using tcu::Android::internal::LibUI; using tcu::Android::internal::GraphicBuffer; using tcu::Android::internal::PixelFormat; using tcu::Android::internal::status_t; PixelFormat getPixelFormat (GLenum format) { switch (format) { case GL_RGB565: return tcu::Android::internal::PIXEL_FORMAT_RGB_565; case GL_RGB8: return tcu::Android::internal::PIXEL_FORMAT_RGB_888; case GL_RGBA4: return tcu::Android::internal::PIXEL_FORMAT_RGBA_4444; case GL_RGB5_A1: return tcu::Android::internal::PIXEL_FORMAT_RGBA_5551; case GL_RGBA8: return tcu::Android::internal::PIXEL_FORMAT_RGBA_8888; default: TCU_THROW(NotSupportedError, "Texture format unsupported by Android"); } } class AndroidNativeClientBuffer : public ClientBuffer { public: AndroidNativeClientBuffer (const LibUI& lib, GLenum format); EGLClientBuffer get (void) const { return reinterpret_cast<EGLClientBuffer>(m_windowBuffer); } GraphicBuffer& getGraphicBuffer (void) { return m_graphicBuffer; } private: GraphicBuffer m_graphicBuffer; ANativeWindowBuffer* m_windowBuffer; }; AndroidNativeClientBuffer::AndroidNativeClientBuffer (const LibUI& lib, GLenum format) : m_graphicBuffer (lib, 64, 64, getPixelFormat(format), GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_RARELY | GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_HW_RENDER) , m_windowBuffer (m_graphicBuffer.getNativeBuffer()) { } class AndroidNativeImageSource : public ImageSource { public: AndroidNativeImageSource (GLenum format) : m_format(format), m_libui(DE_NULL) {} ~AndroidNativeImageSource (void); MovePtr<ClientBuffer> createBuffer (const glw::Functions&, Texture2D*) const; string getRequiredExtension (void) const { return "EGL_ANDROID_image_native_buffer"; } EGLImageKHR createImage (const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const; GLenum getEffectiveFormat (void) const { return m_format; } protected: GLenum m_format; const LibUI& getLibUI (void) const; private: mutable LibUI* m_libui; }; AndroidNativeImageSource::~AndroidNativeImageSource (void) { delete m_libui; } const LibUI& AndroidNativeImageSource::getLibUI (void) const { if (!m_libui) m_libui = new LibUI(); return *m_libui; } void checkStatus (status_t status) { if (status != tcu::Android::internal::OK) TCU_FAIL(("Android error: status code " + de::toString(status)).c_str()); } MovePtr<ClientBuffer> AndroidNativeImageSource::createBuffer (const glw::Functions&, Texture2D* ref) const { MovePtr<AndroidNativeClientBuffer> buffer (new AndroidNativeClientBuffer(getLibUI(), m_format)); GraphicBuffer& graphicBuffer = buffer->getGraphicBuffer(); if (ref != DE_NULL) { const TextureFormat texFormat = glu::mapGLInternalFormat(m_format); void* bufferData = DE_NULL; *ref = Texture2D(texFormat, 64, 64); ref->allocLevel(0); tcu::fillWithComponentGradients(ref->getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); checkStatus(graphicBuffer.lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, &bufferData)); { PixelBufferAccess nativeBuffer(texFormat, 64, 64, 1, bufferData); tcu::copy(nativeBuffer, ref->getLevel(0)); } checkStatus(graphicBuffer.unlock()); } return MovePtr<ClientBuffer>(buffer); } EGLImageKHR AndroidNativeImageSource::createImage (const Library& egl, EGLDisplay dpy, EGLContext, EGLClientBuffer clientBuffer) const { static const EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; const EGLImageKHR image = egl.createImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs); EGLU_CHECK_MSG(egl, "eglCreateImageKHR()"); return image; } MovePtr<ImageSource> createAndroidNativeImageSource (GLenum format) { try { return MovePtr<ImageSource>(new AndroidNativeImageSource(format)); } catch (const std::runtime_error& exc) { return createUnsupportedImageSource(string("Android native buffers unsupported: ") + exc.what(), format); } } #endif // DE_OS == DE_OS_ANDROID } // Image } // egl } // deqp