Commit 4e6f6545 by Geoff Lang Committed by Commit Bot

GLX: Support X11 pixmaps

Add support for creating EGL pixmaps from X11 pixmaps using GLX. Pixmaps are needed for various external APIs such as VAAPI. Add support for EGL_NOK_texture_from_pixmap to allow binding pixmaps to textures. BUG=angleproject:4560 Change-Id: I4a6d3ad7e87151ff5317bbdaaf093ac1b46daf5f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2153805 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 0eae0d6c
...@@ -1181,6 +1181,8 @@ const char *GetGenericErrorMessage(EGLint error) ...@@ -1181,6 +1181,8 @@ const char *GetGenericErrorMessage(EGLint error)
return "Bad match."; return "Bad match.";
case EGL_BAD_NATIVE_WINDOW: case EGL_BAD_NATIVE_WINDOW:
return "Bad native window."; return "Bad native window.";
case EGL_BAD_NATIVE_PIXMAP:
return "Bad native pixmap.";
case EGL_BAD_PARAMETER: case EGL_BAD_PARAMETER:
return "Bad parameter."; return "Bad parameter.";
case EGL_BAD_SURFACE: case EGL_BAD_SURFACE:
......
...@@ -1392,7 +1392,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -1392,7 +1392,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_KHR_create_context_no_error", createContextNoError, &extensionStrings); InsertExtensionString("EGL_KHR_create_context_no_error", createContextNoError, &extensionStrings);
InsertExtensionString("EGL_EXT_image_dma_buf_import", imageDmaBufImportEXT, &extensionStrings); InsertExtensionString("EGL_EXT_image_dma_buf_import", imageDmaBufImportEXT, &extensionStrings);
InsertExtensionString("EGL_EXT_image_dma_buf_import_modifiers", imageDmaBufImportModifiersEXT, &extensionStrings); InsertExtensionString("EGL_EXT_image_dma_buf_import_modifiers", imageDmaBufImportModifiersEXT, &extensionStrings);
InsertExtensionString("EGL_NOK_texture_from_pixmap", textureFromPixmapNOK, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
......
...@@ -1082,6 +1082,9 @@ struct DisplayExtensions ...@@ -1082,6 +1082,9 @@ struct DisplayExtensions
// EGL_EXT_image_dma_buf_import_modifiers // EGL_EXT_image_dma_buf_import_modifiers
bool imageDmaBufImportModifiersEXT = false; bool imageDmaBufImportModifiersEXT = false;
// EGL_NOK_texture_from_pixmap
bool textureFromPixmapNOK = false;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -62,7 +62,8 @@ Config::Config() ...@@ -62,7 +62,8 @@ Config::Config()
optimalOrientation(0), optimalOrientation(0),
colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT), colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
recordable(EGL_FALSE), recordable(EGL_FALSE),
framebufferTarget(EGL_FALSE) // TODO: http://anglebug.com/4208 framebufferTarget(EGL_FALSE), // TODO: http://anglebug.com/4208
yInverted(EGL_FALSE)
{} {}
Config::~Config() {} Config::~Config() {}
...@@ -368,6 +369,9 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) ...@@ -368,6 +369,9 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap)
case EGL_FRAMEBUFFER_TARGET_ANDROID: case EGL_FRAMEBUFFER_TARGET_ANDROID:
match = config.framebufferTarget == static_cast<EGLBoolean>(attributeValue); match = config.framebufferTarget == static_cast<EGLBoolean>(attributeValue);
break; break;
case EGL_Y_INVERTED_NOK:
match = config.yInverted == static_cast<EGLBoolean>(attributeValue);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -74,6 +74,9 @@ struct Config ...@@ -74,6 +74,9 @@ struct Config
EGLBoolean framebufferTarget; // EGL_TRUE if the config supports rendering to a ANativeWindow EGLBoolean framebufferTarget; // EGL_TRUE if the config supports rendering to a ANativeWindow
// for which the buffers are passed to the HWComposer HAL as a // for which the buffers are passed to the HWComposer HAL as a
// framebuffer target layer. // framebuffer target layer.
EGLBoolean yInverted; // True if the drawable's framebuffer is y-inverted. This can be used to
// determine if y-inverted texture coordinates need to be used when
// texturing from this drawable when it is bound to a texture target.
}; };
class ConfigSet class ConfigSet
......
...@@ -1586,6 +1586,13 @@ Error Display::validateImageClientBuffer(const gl::Context *context, ...@@ -1586,6 +1586,13 @@ Error Display::validateImageClientBuffer(const gl::Context *context,
return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs); return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
} }
Error Display::valdiatePixmap(Config *config,
EGLNativePixmapType pixmap,
const AttributeMap &attributes) const
{
return mImplementation->validatePixmap(config, pixmap, attributes);
}
bool Display::isValidDisplay(const egl::Display *display) bool Display::isValidDisplay(const egl::Display *display)
{ {
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap(); const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
......
...@@ -172,6 +172,9 @@ class Display final : public LabeledObject, angle::NonCopyable ...@@ -172,6 +172,9 @@ class Display final : public LabeledObject, angle::NonCopyable
EGLenum target, EGLenum target,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const; const egl::AttributeMap &attribs) const;
Error valdiatePixmap(Config *config,
EGLNativePixmapType pixmap,
const AttributeMap &attributes) const;
static bool isValidDisplay(const Display *display); static bool isValidDisplay(const Display *display);
static bool isValidNativeDisplay(EGLNativeDisplayType display); static bool isValidNativeDisplay(EGLNativeDisplayType display);
......
...@@ -100,6 +100,7 @@ using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>; ...@@ -100,6 +100,7 @@ using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>;
using EglBadDisplay = priv::ErrorStream<EGL_BAD_DISPLAY>; using EglBadDisplay = priv::ErrorStream<EGL_BAD_DISPLAY>;
using EglBadMatch = priv::ErrorStream<EGL_BAD_MATCH>; using EglBadMatch = priv::ErrorStream<EGL_BAD_MATCH>;
using EglBadNativeWindow = priv::ErrorStream<EGL_BAD_NATIVE_WINDOW>; using EglBadNativeWindow = priv::ErrorStream<EGL_BAD_NATIVE_WINDOW>;
using EglBadNativePixmap = priv::ErrorStream<EGL_BAD_NATIVE_PIXMAP>;
using EglBadParameter = priv::ErrorStream<EGL_BAD_PARAMETER>; using EglBadParameter = priv::ErrorStream<EGL_BAD_PARAMETER>;
using EglBadState = priv::ErrorStream<EGL_BAD_STATE_KHR>; using EglBadState = priv::ErrorStream<EGL_BAD_STATE_KHR>;
using EglBadStream = priv::ErrorStream<EGL_BAD_STREAM_KHR>; using EglBadStream = priv::ErrorStream<EGL_BAD_STREAM_KHR>;
......
...@@ -91,6 +91,11 @@ Surface::Surface(EGLint surfaceType, ...@@ -91,6 +91,11 @@ Surface::Surface(EGLint surfaceType,
mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE); mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
} }
if (mType == EGL_PIXMAP_BIT)
{
mRenderBuffer = EGL_SINGLE_BUFFER;
}
mGLColorspace = mGLColorspace =
static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR)); static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
mVGAlphaFormat = mVGAlphaFormat =
......
...@@ -52,6 +52,14 @@ egl::Error DisplayImpl::validateImageClientBuffer(const gl::Context *context, ...@@ -52,6 +52,14 @@ egl::Error DisplayImpl::validateImageClientBuffer(const gl::Context *context,
return egl::EglBadDisplay() << "DisplayImpl::validateImageClientBuffer unimplemented."; return egl::EglBadDisplay() << "DisplayImpl::validateImageClientBuffer unimplemented.";
} }
egl::Error DisplayImpl::validatePixmap(egl::Config *config,
EGLNativePixmapType pixmap,
const egl::AttributeMap &attributes) const
{
UNREACHABLE();
return egl::EglBadDisplay() << "DisplayImpl::valdiatePixmap unimplemented.";
}
const egl::Caps &DisplayImpl::getCaps() const const egl::Caps &DisplayImpl::getCaps() const
{ {
if (!mCapsInitialized) if (!mCapsInitialized)
......
...@@ -85,6 +85,9 @@ class DisplayImpl : public EGLImplFactory ...@@ -85,6 +85,9 @@ class DisplayImpl : public EGLImplFactory
EGLenum target, EGLenum target,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const; const egl::AttributeMap &attribs) const;
virtual egl::Error validatePixmap(egl::Config *config,
EGLNativePixmapType pixmap,
const egl::AttributeMap &attributes) const;
virtual std::string getVendorString() const = 0; virtual std::string getVendorString() const = 0;
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/ContextGL.h" #include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h" #include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
#include "libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h"
#include "libANGLE/renderer/gl/glx/RendererGLX.h" #include "libANGLE/renderer/gl/glx/RendererGLX.h"
#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h" #include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
#include "libANGLE/renderer/gl/glx/glx_utils.h"
#include "libANGLE/renderer/gl/renderergl_utils.h" #include "libANGLE/renderer/gl/renderergl_utils.h"
namespace namespace
...@@ -426,8 +428,31 @@ SurfaceImpl *DisplayGLX::createPixmapSurface(const egl::SurfaceState &state, ...@@ -426,8 +428,31 @@ SurfaceImpl *DisplayGLX::createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap, NativePixmapType nativePixmap,
const egl::AttributeMap &attribs) const egl::AttributeMap &attribs)
{ {
UNIMPLEMENTED(); ASSERT(configIdToGLXConfig.count(state.config->configID) > 0);
return nullptr; glx::FBConfig fbConfig = configIdToGLXConfig[state.config->configID];
return new PixmapSurfaceGLX(state, nativePixmap, mGLX.getDisplay(), mGLX, fbConfig);
}
egl::Error DisplayGLX::validatePixmap(egl::Config *config,
EGLNativePixmapType pixmap,
const egl::AttributeMap &attributes) const
{
Window rootWindow;
int x = 0;
int y = 0;
unsigned int width = 0;
unsigned int height = 0;
unsigned int borderWidth = 0;
unsigned int depth = 0;
int status = XGetGeometry(mGLX.getDisplay(), pixmap, &rootWindow, &x, &y, &width, &height,
&borderWidth, &depth);
if (!status)
{
return egl::EglBadNativePixmap() << "Invalid native pixmap, XGetGeometry failed: "
<< x11::XErrorToString(mXDisplay, status);
}
return egl::NoError();
} }
ContextImpl *DisplayGLX::createContext(const gl::State &state, ContextImpl *DisplayGLX::createContext(const gl::State &state,
...@@ -654,14 +679,6 @@ egl::ConfigSet DisplayGLX::generateConfigs() ...@@ -654,14 +679,6 @@ egl::ConfigSet DisplayGLX::generateConfigs()
// Misc // Misc
config.level = getGLXFBConfigAttrib(glxConfig, GLX_LEVEL); config.level = getGLXFBConfigAttrib(glxConfig, GLX_LEVEL);
config.bindToTextureRGB = EGL_FALSE;
config.bindToTextureRGBA = EGL_FALSE;
int glxDrawable = getGLXFBConfigAttrib(glxConfig, GLX_DRAWABLE_TYPE);
config.surfaceType = 0 | (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) |
(glxDrawable & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0) |
(glxDrawable & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0);
config.minSwapInterval = mMinSwapInterval; config.minSwapInterval = mMinSwapInterval;
config.maxSwapInterval = mMaxSwapInterval; config.maxSwapInterval = mMaxSwapInterval;
...@@ -678,6 +695,39 @@ egl::ConfigSet DisplayGLX::generateConfigs() ...@@ -678,6 +695,39 @@ egl::ConfigSet DisplayGLX::generateConfigs()
config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
// GLX doesn't support binding pbuffers to textures and there is no way to differentiate in
// EGL that pixmaps can be bound but pbuffers cannot. If both pixmaps and pbuffers are
// supported, generate extra configs with either pbuffer or pixmap support.
int glxDrawable = getGLXFBConfigAttrib(glxConfig, GLX_DRAWABLE_TYPE);
bool pbufferSupport = (glxDrawable & EGL_PBUFFER_BIT) != 0;
bool pixmapSupport = (glxDrawable & GLX_PIXMAP_BIT) != 0;
bool pixmapBindToTextureSupport =
pixmapSupport && mGLX.hasExtension("GLX_EXT_texture_from_pixmap");
if (pbufferSupport && pixmapBindToTextureSupport)
{
// Generate the pixmap-only config
config.surfaceType = (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) |
(pixmapSupport ? EGL_PIXMAP_BIT : 0);
config.bindToTextureRGB = getGLXFBConfigAttrib(glxConfig, GLX_BIND_TO_TEXTURE_RGB_EXT);
config.bindToTextureRGBA =
getGLXFBConfigAttrib(glxConfig, GLX_BIND_TO_TEXTURE_RGBA_EXT);
config.yInverted = getGLXFBConfigAttrib(glxConfig, GLX_Y_INVERTED_EXT);
int id = configs.add(config);
configIdToGLXConfig[id] = glxConfig;
}
// Generate the pbuffer config. It can support pixmaps but not bind-to-texture.
config.surfaceType = (glxDrawable & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0) |
(pbufferSupport ? EGL_PBUFFER_BIT : 0) |
(pixmapSupport ? EGL_PIXMAP_BIT : 0);
config.bindToTextureRGB = false;
config.bindToTextureRGBA = false;
config.yInverted = false;
int id = configs.add(config); int id = configs.add(config);
configIdToGLXConfig[id] = glxConfig; configIdToGLXConfig[id] = glxConfig;
} }
...@@ -830,6 +880,8 @@ void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const ...@@ -830,6 +880,8 @@ void DisplayGLX::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->syncControlCHROMIUM = hasSyncControlOML; outExtensions->syncControlCHROMIUM = hasSyncControlOML;
outExtensions->syncControlRateANGLE = hasSyncControlOML; outExtensions->syncControlRateANGLE = hasSyncControlOML;
outExtensions->textureFromPixmapNOK = mGLX.hasExtension("GLX_EXT_texture_from_pixmap");
DisplayGL::generateExtensions(outExtensions); DisplayGL::generateExtensions(outExtensions);
} }
......
...@@ -50,6 +50,10 @@ class DisplayGLX : public DisplayGL ...@@ -50,6 +50,10 @@ class DisplayGLX : public DisplayGL
NativePixmapType nativePixmap, NativePixmapType nativePixmap,
const egl::AttributeMap &attribs) override; const egl::AttributeMap &attribs) override;
egl::Error validatePixmap(egl::Config *config,
EGLNativePixmapType pixmap,
const egl::AttributeMap &attributes) const override;
ContextImpl *createContext(const gl::State &state, ContextImpl *createContext(const gl::State &state,
gl::ErrorSet *errorSet, gl::ErrorSet *errorSet,
const egl::Config *configuration, const egl::Config *configuration,
......
...@@ -56,12 +56,16 @@ struct FunctionsGLX::GLXFunctionTable ...@@ -56,12 +56,16 @@ struct FunctionsGLX::GLXFunctionTable
createPbufferPtr(nullptr), createPbufferPtr(nullptr),
destroyPbufferPtr(nullptr), destroyPbufferPtr(nullptr),
queryDrawablePtr(nullptr), queryDrawablePtr(nullptr),
createPixmapPtr(nullptr),
destroyPixmapPtr(nullptr),
createContextAttribsARBPtr(nullptr), createContextAttribsARBPtr(nullptr),
swapIntervalEXTPtr(nullptr), swapIntervalEXTPtr(nullptr),
swapIntervalMESAPtr(nullptr), swapIntervalMESAPtr(nullptr),
swapIntervalSGIPtr(nullptr), swapIntervalSGIPtr(nullptr),
getSyncValuesOMLPtr(nullptr), getSyncValuesOMLPtr(nullptr),
getMscRateOMLPtr(nullptr) getMscRateOMLPtr(nullptr),
bindTexImageEXTPtr(nullptr),
releaseTexImageEXTPtr(nullptr)
{} {}
// GLX 1.0 // GLX 1.0
...@@ -90,6 +94,8 @@ struct FunctionsGLX::GLXFunctionTable ...@@ -90,6 +94,8 @@ struct FunctionsGLX::GLXFunctionTable
PFNGLXCREATEPBUFFERPROC createPbufferPtr; PFNGLXCREATEPBUFFERPROC createPbufferPtr;
PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr; PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
PFNGLXQUERYDRAWABLEPROC queryDrawablePtr; PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;
PFNGLXCREATEPIXMAPPROC createPixmapPtr;
PFNGLXDESTROYPIXMAPPROC destroyPixmapPtr;
// GLX_ARB_create_context // GLX_ARB_create_context
PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr; PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;
...@@ -106,6 +112,10 @@ struct FunctionsGLX::GLXFunctionTable ...@@ -106,6 +112,10 @@ struct FunctionsGLX::GLXFunctionTable
// GLX_OML_sync_control // GLX_OML_sync_control
PFNGLXGETSYNCVALUESOMLPROC getSyncValuesOMLPtr; PFNGLXGETSYNCVALUESOMLPROC getSyncValuesOMLPtr;
PFNGLXGETMSCRATEOMLPROC getMscRateOMLPtr; PFNGLXGETMSCRATEOMLPROC getMscRateOMLPtr;
// GLX_EXT_texture_from_pixmap
PFNGLXBINDTEXIMAGEEXTPROC bindTexImageEXTPtr;
PFNGLXRELEASETEXIMAGEEXTPROC releaseTexImageEXTPtr;
}; };
FunctionsGLX::FunctionsGLX() FunctionsGLX::FunctionsGLX()
...@@ -228,6 +238,8 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS ...@@ -228,6 +238,8 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer); GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer); GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable); GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);
GET_FNPTR_OR_ERROR(&mFnPtrs->createPixmapPtr, glXCreatePixmap);
GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPixmapPtr, glXDestroyPixmap);
// Extensions // Extensions
if (hasExtension("GLX_ARB_create_context")) if (hasExtension("GLX_ARB_create_context"))
...@@ -251,6 +263,11 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS ...@@ -251,6 +263,11 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
GET_PROC_OR_ERROR(&mFnPtrs->getSyncValuesOMLPtr, glXGetSyncValuesOML); GET_PROC_OR_ERROR(&mFnPtrs->getSyncValuesOMLPtr, glXGetSyncValuesOML);
GET_PROC_OR_ERROR(&mFnPtrs->getMscRateOMLPtr, glXGetMscRateOML); GET_PROC_OR_ERROR(&mFnPtrs->getMscRateOMLPtr, glXGetMscRateOML);
} }
if (hasExtension("GLX_EXT_texture_from_pixmap"))
{
GET_PROC_OR_ERROR(&mFnPtrs->bindTexImageEXTPtr, glXBindTexImageEXT);
GET_PROC_OR_ERROR(&mFnPtrs->releaseTexImageEXTPtr, glXReleaseTexImageEXT);
}
#undef GET_FNPTR_OR_ERROR #undef GET_FNPTR_OR_ERROR
#undef GET_PROC_OR_ERROR #undef GET_PROC_OR_ERROR
...@@ -383,6 +400,18 @@ void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned ...@@ -383,6 +400,18 @@ void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned
mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value); mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
} }
glx::Pixmap FunctionsGLX::createPixmap(glx::FBConfig config,
Pixmap pixmap,
const int *attribList) const
{
GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
return mFnPtrs->createPixmapPtr(mXDisplay, cfg, pixmap, attribList);
}
void FunctionsGLX::destroyPixmap(Pixmap pixmap) const
{
mFnPtrs->destroyPixmapPtr(mXDisplay, pixmap);
}
// GLX_ARB_create_context // GLX_ARB_create_context
glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config, glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config,
glx::Context shareContext, glx::Context shareContext,
...@@ -426,4 +455,12 @@ bool FunctionsGLX::getMscRateOML(glx::Drawable drawable, ...@@ -426,4 +455,12 @@ bool FunctionsGLX::getMscRateOML(glx::Drawable drawable,
return mFnPtrs->getMscRateOMLPtr(mXDisplay, drawable, numerator, denominator); return mFnPtrs->getMscRateOMLPtr(mXDisplay, drawable, numerator, denominator);
} }
void FunctionsGLX::bindTexImageEXT(glx::Drawable drawable, int buffer, const int *attribList) const
{
mFnPtrs->bindTexImageEXTPtr(mXDisplay, drawable, buffer, attribList);
}
void FunctionsGLX::releaseTexImageEXT(glx::Drawable drawable, int buffer) const
{
mFnPtrs->releaseTexImageEXTPtr(mXDisplay, drawable, buffer);
}
} // namespace rx } // namespace rx
...@@ -62,6 +62,8 @@ class FunctionsGLX ...@@ -62,6 +62,8 @@ class FunctionsGLX
glx::Pbuffer createPbuffer(glx::FBConfig config, const int *attribList) const; glx::Pbuffer createPbuffer(glx::FBConfig config, const int *attribList) const;
void destroyPbuffer(glx::Pbuffer pbuffer) const; void destroyPbuffer(glx::Pbuffer pbuffer) const;
void queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const; void queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const;
glx::Pixmap createPixmap(glx::FBConfig config, Pixmap pixmap, const int *attribList) const;
void destroyPixmap(Pixmap pixmap) const;
// GLX_ARB_create_context // GLX_ARB_create_context
glx::Context createContextAttribsARB(glx::FBConfig config, glx::Context createContextAttribsARB(glx::FBConfig config,
...@@ -82,6 +84,10 @@ class FunctionsGLX ...@@ -82,6 +84,10 @@ class FunctionsGLX
bool getSyncValuesOML(glx::Drawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc) const; bool getSyncValuesOML(glx::Drawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc) const;
bool getMscRateOML(glx::Drawable drawable, int32_t *numerator, int32_t *denominator) const; bool getMscRateOML(glx::Drawable drawable, int32_t *numerator, int32_t *denominator) const;
// GLX_EXT_texture_from_pixmap
void bindTexImageEXT(glx::Drawable drawable, int buffer, const int *attribList) const;
void releaseTexImageEXT(glx::Drawable drawable, int buffer) const;
private: private:
// So as to isolate GLX from angle we do not include angleutils.h and cannot // So as to isolate GLX from angle we do not include angleutils.h and cannot
// use angle::NonCopyable so we replicated it here instead. // use angle::NonCopyable so we replicated it here instead.
......
//
// Copyright 2020 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.
//
// PixmapSurfaceGLX.cpp: GLX implementation of egl::Surface for Pixmaps
#include "libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h"
#include "common/debug.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
#include "libANGLE/renderer/gl/glx/glx_utils.h"
#include <iostream>
namespace rx
{
namespace
{
int EGLTextureFormatToGLXTextureFormat(EGLint textureFormat)
{
switch (textureFormat)
{
case EGL_NO_TEXTURE:
return GLX_TEXTURE_FORMAT_NONE_EXT;
case EGL_TEXTURE_RGB:
return GLX_TEXTURE_FORMAT_RGB_EXT;
case EGL_TEXTURE_RGBA:
return GLX_TEXTURE_FORMAT_RGBA_EXT;
default:
UNREACHABLE();
return GLX_TEXTURE_FORMAT_NONE_EXT;
}
}
int EGLTextureTargetToGLXTextureTarget(EGLint textureTarget)
{
switch (textureTarget)
{
case EGL_NO_TEXTURE:
return 0;
case EGL_TEXTURE_2D:
return GLX_TEXTURE_2D_EXT;
default:
UNREACHABLE();
return 0;
}
}
int EGLBufferToGLXBuffer(EGLint buffer)
{
switch (buffer)
{
case EGL_BACK_BUFFER:
return GLX_BACK_EXT;
default:
UNREACHABLE();
return 0;
}
}
} // namespace
PixmapSurfaceGLX::PixmapSurfaceGLX(const egl::SurfaceState &state,
Pixmap pixmap,
Display *display,
const FunctionsGLX &glx,
glx::FBConfig fbConfig)
: SurfaceGLX(state),
mWidth(0),
mHeight(0),
mGLX(glx),
mFBConfig(fbConfig),
mXPixmap(pixmap),
mGLXPixmap(0),
mDisplay(display)
{}
PixmapSurfaceGLX::~PixmapSurfaceGLX()
{
if (mGLXPixmap)
{
mGLX.destroyPixmap(mGLXPixmap);
}
}
egl::Error PixmapSurfaceGLX::initialize(const egl::Display *display)
{
DisplayGLX *displayGLX = GetImplAs<DisplayGLX>(display);
{
Window rootWindow;
int x = 0;
int y = 0;
unsigned int borderWidth = 0;
unsigned int depth = 0;
int status = XGetGeometry(mDisplay, mXPixmap, &rootWindow, &x, &y, &mWidth, &mHeight,
&borderWidth, &depth);
if (!status)
{
return egl::EglBadSurface() << "XGetGeometry query failed on pixmap surface: "
<< x11::XErrorToString(mDisplay, status);
}
}
std::vector<int> pixmapAttribs;
if (mState.attributes.contains(EGL_TEXTURE_FORMAT))
{
pixmapAttribs.push_back(GLX_TEXTURE_FORMAT_EXT);
pixmapAttribs.push_back(
EGLTextureFormatToGLXTextureFormat(mState.attributes.getAsInt(EGL_TEXTURE_FORMAT)));
}
if (mState.attributes.contains(EGL_TEXTURE_TARGET))
{
pixmapAttribs.push_back(GLX_TEXTURE_TARGET_EXT);
pixmapAttribs.push_back(
EGLTextureTargetToGLXTextureTarget(mState.attributes.getAsInt(EGL_TEXTURE_TARGET)));
}
pixmapAttribs.push_back(None);
mGLXPixmap = mGLX.createPixmap(mFBConfig, mXPixmap, pixmapAttribs.data());
if (!mGLXPixmap)
{
return egl::EglBadAlloc() << "Failed to create a native GLX pixmap.";
}
XFlush(mDisplay);
displayGLX->syncXCommands();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::makeCurrent(const gl::Context *context)
{
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::swap(const gl::Context *context)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::postSubBuffer(const gl::Context *context,
EGLint x,
EGLint y,
EGLint width,
EGLint height)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::bindTexImage(const gl::Context *context,
gl::Texture *texture,
EGLint buffer)
{
const int attribs[] = {None};
mGLX.bindTexImageEXT(mGLXPixmap, EGLBufferToGLXBuffer(buffer), attribs);
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::releaseTexImage(const gl::Context *context, EGLint buffer)
{
mGLX.releaseTexImageEXT(mGLXPixmap, EGLBufferToGLXBuffer(buffer));
return egl::NoError();
}
void PixmapSurfaceGLX::setSwapInterval(EGLint interval) {}
EGLint PixmapSurfaceGLX::getWidth() const
{
return mWidth;
}
EGLint PixmapSurfaceGLX::getHeight() const
{
return mHeight;
}
EGLint PixmapSurfaceGLX::isPostSubBufferSupported() const
{
UNREACHABLE();
return EGL_FALSE;
}
EGLint PixmapSurfaceGLX::getSwapBehavior() const
{
return EGL_BUFFER_DESTROYED;
}
egl::Error PixmapSurfaceGLX::checkForResize()
{
// The size of pbuffers never change
return egl::NoError();
}
glx::Drawable PixmapSurfaceGLX::getDrawable() const
{
return mGLXPixmap;
}
} // namespace rx
//
// Copyright 2020 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.
//
// PixmapSurfaceGLX.h: GLX implementation of egl::Surface for Pixmaps
#ifndef LIBANGLE_RENDERER_GL_GLX_PIXMAPSURFACEGLX_H_
#define LIBANGLE_RENDERER_GL_GLX_PIXMAPSURFACEGLX_H_
#include "libANGLE/renderer/gl/glx/SurfaceGLX.h"
#include "libANGLE/renderer/gl/glx/platform_glx.h"
namespace rx
{
class FunctionsGLX;
class PixmapSurfaceGLX : public SurfaceGLX
{
public:
PixmapSurfaceGLX(const egl::SurfaceState &state,
Pixmap pixmap,
Display *display,
const FunctionsGLX &glx,
glx::FBConfig fbConfig);
~PixmapSurfaceGLX() override;
egl::Error initialize(const egl::Display *display) override;
egl::Error makeCurrent(const gl::Context *context) override;
egl::Error swap(const gl::Context *context) override;
egl::Error postSubBuffer(const gl::Context *context,
EGLint x,
EGLint y,
EGLint width,
EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
egl::Error bindTexImage(const gl::Context *context,
gl::Texture *texture,
EGLint buffer) override;
egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
void setSwapInterval(EGLint interval) override;
EGLint getWidth() const override;
EGLint getHeight() const override;
EGLint isPostSubBufferSupported() const override;
EGLint getSwapBehavior() const override;
egl::Error checkForResize() override;
glx::Drawable getDrawable() const override;
private:
unsigned mWidth;
unsigned mHeight;
const FunctionsGLX &mGLX;
glx::FBConfig mFBConfig;
Pixmap mXPixmap;
glx::Pixmap mGLXPixmap;
Display *mDisplay;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_GL_GLX_PIXMAPSURFACEGLX_H_
//
// Copyright 2020 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.
//
// glx_utils.cpp: Utility routines specific to the G:X->EGL implementation.
#include "libANGLE/renderer/gl/glx/glx_utils.h"
#include "common/angleutils.h"
namespace rx
{
namespace x11
{
std::string XErrorToString(Display *display, int status)
{
// Write nulls to the buffer so that if XGetErrorText fails, converting to an std::string will
// be an empty string.
char buffer[256] = {0};
XGetErrorText(display, status, buffer, ArraySize(buffer));
return std::string(buffer);
}
} // namespace x11
} // namespace rx
//
// Copyright 2020 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.
//
// glx_utils.h: Utility routines specific to the G:X->EGL implementation.
#ifndef LIBANGLE_RENDERER_GL_GLX_GLXUTILS_H_
#define LIBANGLE_RENDERER_GL_GLX_GLXUTILS_H_
#include <string>
#include "common/platform.h"
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
namespace rx
{
namespace x11
{
std::string XErrorToString(Display *display, int status);
} // namespace x11
} // namespace rx
#endif // LIBANGLE_RENDERER_GL_GLX_GLXUTILS_H_
...@@ -232,6 +232,13 @@ Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute) ...@@ -232,6 +232,13 @@ Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute)
} }
break; break;
case EGL_Y_INVERTED_NOK:
if (!display->getExtensions().textureFromPixmapNOK)
{
return EglBadAttribute() << "EGL_NOK_texture_from_pixmap is not enabled.";
}
break;
default: default:
return EglBadAttribute() << "Unknown attribute."; return EglBadAttribute() << "Unknown attribute.";
} }
...@@ -1953,6 +1960,85 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, ...@@ -1953,6 +1960,85 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
return NoError(); return NoError();
} }
Error ValidateCreatePixmapSurface(Display *display,
Config *config,
EGLNativePixmapType pixmap,
const AttributeMap &attributes)
{
ANGLE_TRY(ValidateConfig(display, config));
const DisplayExtensions &displayExtensions = display->getExtensions();
for (AttributeMap::const_iterator attributeIter = attributes.begin();
attributeIter != attributes.end(); attributeIter++)
{
EGLAttrib attribute = attributeIter->first;
EGLAttrib value = attributeIter->second;
switch (attribute)
{
case EGL_GL_COLORSPACE:
ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
break;
case EGL_VG_COLORSPACE:
break;
case EGL_VG_ALPHA_FORMAT:
break;
case EGL_TEXTURE_FORMAT:
if (!displayExtensions.textureFromPixmapNOK)
{
return EglBadAttribute() << "EGL_NOK_texture_from_pixmap is not enabled.";
}
switch (value)
{
case EGL_NO_TEXTURE:
case EGL_TEXTURE_RGB:
case EGL_TEXTURE_RGBA:
break;
default:
return EglBadAttribute();
}
break;
case EGL_TEXTURE_TARGET:
if (!displayExtensions.textureFromPixmapNOK)
{
return EglBadAttribute() << "EGL_NOK_texture_from_pixmap is not enabled.";
}
switch (value)
{
case EGL_NO_TEXTURE:
case EGL_TEXTURE_2D:
break;
default:
return EglBadAttribute();
}
break;
case EGL_MIPMAP_TEXTURE:
if (!displayExtensions.textureFromPixmapNOK)
{
return EglBadAttribute() << "EGL_NOK_texture_from_pixmap is not enabled.";
}
break;
default:
return EglBadAttribute() << "Unknown attribute";
}
}
if (!(config->surfaceType & EGL_PIXMAP_BIT))
{
return EglBadMatch() << "Congfig does not suport pixmaps.";
}
ANGLE_TRY(display->valdiatePixmap(config, pixmap, attributes));
return NoError();
}
Error ValidateMakeCurrent(Display *display, Surface *draw, Surface *read, gl::Context *context) Error ValidateMakeCurrent(Display *display, Surface *draw, Surface *read, gl::Context *context)
{ {
if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)) if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
......
...@@ -83,6 +83,11 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, ...@@ -83,6 +83,11 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
Config *config, Config *config,
const AttributeMap &attributes); const AttributeMap &attributes);
Error ValidateCreatePixmapSurface(Display *display,
Config *config,
EGLNativePixmapType pixmap,
const AttributeMap &attributes);
Error ValidateMakeCurrent(Display *display, Surface *draw, Surface *read, gl::Context *context); Error ValidateMakeCurrent(Display *display, Surface *draw, Surface *read, gl::Context *context);
Error ValidateCreateImage(const Display *display, Error ValidateCreateImage(const Display *display,
......
...@@ -807,12 +807,16 @@ libangle_gl_glx_sources = [ ...@@ -807,12 +807,16 @@ libangle_gl_glx_sources = [
"src/libANGLE/renderer/gl/glx/FunctionsGLX.h", "src/libANGLE/renderer/gl/glx/FunctionsGLX.h",
"src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp", "src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp",
"src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h", "src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h",
"src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.cpp",
"src/libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h",
"src/libANGLE/renderer/gl/glx/RendererGLX.cpp", "src/libANGLE/renderer/gl/glx/RendererGLX.cpp",
"src/libANGLE/renderer/gl/glx/RendererGLX.h", "src/libANGLE/renderer/gl/glx/RendererGLX.h",
"src/libANGLE/renderer/gl/glx/SurfaceGLX.h", "src/libANGLE/renderer/gl/glx/SurfaceGLX.h",
"src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp", "src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp",
"src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h", "src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h",
"src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h", "src/libANGLE/renderer/gl/glx/functionsglx_typedefs.h",
"src/libANGLE/renderer/gl/glx/glx_utils.cpp",
"src/libANGLE/renderer/gl/glx/glx_utils.h",
"src/libANGLE/renderer/gl/glx/platform_glx.h", "src/libANGLE/renderer/gl/glx/platform_glx.h",
] ]
......
...@@ -305,14 +305,19 @@ EGLSurface EGLAPIENTRY EGL_CreatePixmapSurface(EGLDisplay dpy, ...@@ -305,14 +305,19 @@ EGLSurface EGLAPIENTRY EGL_CreatePixmapSurface(EGLDisplay dpy,
egl::Display *display = static_cast<egl::Display *>(dpy); egl::Display *display = static_cast<egl::Display *>(dpy);
Config *configuration = static_cast<Config *>(config); Config *configuration = static_cast<Config *>(config);
AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
ANGLE_EGL_TRY_RETURN(thread, ValidateConfig(display, configuration), "eglCreatePixmapSurface", ANGLE_EGL_TRY_RETURN(thread,
GetDisplayIfValid(display), EGL_NO_SURFACE); ValidateCreatePixmapSurface(display, configuration, pixmap, attributes),
"eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
UNIMPLEMENTED(); // FIXME egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
display->createPixmapSurface(configuration, pixmap, attributes, &surface),
"eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
thread->setSuccess(); thread->setSuccess();
return EGL_NO_SURFACE; return static_cast<EGLSurface>(surface);
} }
EGLBoolean EGLAPIENTRY EGL_DestroySurface(EGLDisplay dpy, EGLSurface surface) EGLBoolean EGLAPIENTRY EGL_DestroySurface(EGLDisplay dpy, EGLSurface surface)
...@@ -1060,12 +1065,24 @@ EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurface(EGLDisplay dpy, ...@@ -1060,12 +1065,24 @@ EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurface(EGLDisplay dpy,
"const EGLint* attrib_list = 0x%016" PRIxPTR, "const EGLint* attrib_list = 0x%016" PRIxPTR,
(uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list); (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list);
Thread *thread = egl::GetCurrentThread(); Thread *thread = egl::GetCurrentThread();
egl::Display *display = static_cast<egl::Display *>(dpy); egl::Display *display = static_cast<egl::Display *>(dpy);
Config *configuration = static_cast<Config *>(config);
// Use reinterpret_cast since native_window could be a pointer or an actual value.
EGLNativePixmapType pixmap = reinterpret_cast<EGLNativePixmapType>(native_pixmap);
AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
UNIMPLEMENTED(); ANGLE_EGL_TRY_RETURN(
thread->setError(EglBadDisplay() << "eglCreatePlatformPixmapSurface unimplemented.", GetDebug(), thread, ValidateCreatePixmapSurface(display, configuration, pixmap, attributes),
"eglCreatePlatformPixmapSurface", GetDisplayIfValid(display)); "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
return EGL_NO_SURFACE;
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(
thread, display->createPixmapSurface(configuration, pixmap, attributes, &surface),
"eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
thread->setSuccess();
return static_cast<EGLSurface>(surface);
} }
EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
......
...@@ -93,6 +93,7 @@ angle_end2end_tests_sources = [ ...@@ -93,6 +93,7 @@ angle_end2end_tests_sources = [
"gl_tests/PackUnpackTest.cpp", "gl_tests/PackUnpackTest.cpp",
"gl_tests/ParallelShaderCompileTest.cpp", "gl_tests/ParallelShaderCompileTest.cpp",
"gl_tests/PbufferTest.cpp", "gl_tests/PbufferTest.cpp",
"gl_tests/PixmapTest.cpp",
"gl_tests/PointSpritesTest.cpp", "gl_tests/PointSpritesTest.cpp",
"gl_tests/ProgramBinaryTest.cpp", "gl_tests/ProgramBinaryTest.cpp",
"gl_tests/ProgramInterfaceTest.cpp", "gl_tests/ProgramInterfaceTest.cpp",
......
...@@ -106,28 +106,8 @@ ...@@ -106,28 +106,8 @@
2716 WIN VULKAN : dEQP-EGL.functional.preserve_swap.no_preserve.* = FAIL 2716 WIN VULKAN : dEQP-EGL.functional.preserve_swap.no_preserve.* = FAIL
// Linux failures // Linux failures
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles1.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles1_gles2.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles1_gles2_gles3.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles2.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles3.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.single_context.gles1.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.single_context.gles2.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.color_clears.single_context.gles3.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.create_surface.pixmap.rgba8888_depth_stencil = SKIP
2546 LINUX : dEQP-EGL.functional.create_surface.pixmap.rgba8888_no_depth_no_stencil = SKIP
2546 LINUX : dEQP-EGL.functional.negative_api.copy_buffers = SKIP 2546 LINUX : dEQP-EGL.functional.negative_api.copy_buffers = SKIP
2546 LINUX : dEQP-EGL.functional.query_context.get_current_context.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.query_context.get_current_display.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.query_context.get_current_surface.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.query_context.query_context.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.query_surface.set_attribute.pixmap.rgba8888_depth_stencil = SKIP
2546 LINUX : dEQP-EGL.functional.query_surface.set_attribute.pixmap.rgba8888_no_depth_no_stencil = SKIP
2546 LINUX : dEQP-EGL.functional.query_surface.simple.pixmap.rgba8888_depth_stencil = SKIP
2546 LINUX : dEQP-EGL.functional.query_surface.simple.pixmap.rgba8888_no_depth_no_stencil = SKIP
2546 LINUX : dEQP-EGL.functional.render.multi_context.* = SKIP 2546 LINUX : dEQP-EGL.functional.render.multi_context.* = SKIP
2546 LINUX : dEQP-EGL.functional.render.single_context.gles2.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.render.single_context.gles3.rgba8888_pixmap = SKIP
2546 LINUX : dEQP-EGL.functional.thread_cleanup.* = SKIP 2546 LINUX : dEQP-EGL.functional.thread_cleanup.* = SKIP
2546 LINUX : dEQP-EGL.functional.native_color_mapping.native_window.* = FAIL 2546 LINUX : dEQP-EGL.functional.native_color_mapping.native_window.* = FAIL
2546 LINUX : dEQP-EGL.functional.native_coord_mapping.native_window.* = FAIL 2546 LINUX : dEQP-EGL.functional.native_coord_mapping.native_window.* = FAIL
......
...@@ -50,6 +50,16 @@ namespace tcu ...@@ -50,6 +50,16 @@ namespace tcu
namespace namespace
{ {
template <typename destType, typename sourceType>
destType bitCast(sourceType source)
{
constexpr size_t copySize =
sizeof(destType) < sizeof(sourceType) ? sizeof(destType) : sizeof(sourceType);
destType output(0);
memcpy(&output, &source, copySize);
return output;
}
enum enum
{ {
DEFAULT_SURFACE_WIDTH = 400, DEFAULT_SURFACE_WIDTH = 400,
...@@ -74,16 +84,14 @@ constexpr eglu::NativeWindow::Capability kWindowCapabilities = ...@@ -74,16 +84,14 @@ constexpr eglu::NativeWindow::Capability kWindowCapabilities =
class ANGLENativeDisplay : public eglu::NativeDisplay class ANGLENativeDisplay : public eglu::NativeDisplay
{ {
public: public:
explicit ANGLENativeDisplay(std::vector<eglw::EGLAttrib> attribs); explicit ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<eglw::EGLAttrib> attribs);
~ANGLENativeDisplay() override = default; ~ANGLENativeDisplay() override = default;
void *getPlatformNative() override void *getPlatformNative() override
{ {
// On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply // On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply
// use reinterpret_cast<void*>. // use reinterpret_cast<void*>.
void *result = nullptr; return bitCast<void *>(mDeviceContext);
memcpy(&result, &mDeviceContext, sizeof(mDeviceContext));
return result;
} }
const eglw::EGLAttrib *getPlatformAttributes() const override const eglw::EGLAttrib *getPlatformAttributes() const override
{ {
...@@ -169,9 +177,9 @@ class NativeWindow : public eglu::NativeWindow ...@@ -169,9 +177,9 @@ class NativeWindow : public eglu::NativeWindow
// ANGLE NativeDisplay // ANGLE NativeDisplay
ANGLENativeDisplay::ANGLENativeDisplay(std::vector<EGLAttrib> attribs) ANGLENativeDisplay::ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<EGLAttrib> attribs)
: eglu::NativeDisplay(kDisplayCapabilities, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"), : eglu::NativeDisplay(kDisplayCapabilities, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),
mDeviceContext(EGL_DEFAULT_DISPLAY), mDeviceContext(display),
mLibrary(ANGLE_EGL_LIBRARY_FULL_NAME), mLibrary(ANGLE_EGL_LIBRARY_FULL_NAME),
mPlatformAttributes(std::move(attribs)) mPlatformAttributes(std::move(attribs))
{} {}
...@@ -220,24 +228,15 @@ eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativ ...@@ -220,24 +228,15 @@ eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativ
int height) const int height) const
{ {
const eglw::Library &egl = nativeDisplay->getLibrary(); const eglw::Library &egl = nativeDisplay->getLibrary();
int redBits = 0; int nativeVisual = 0;
int greenBits = 0;
int blueBits = 0;
int alphaBits = 0;
int bitSum = 0;
DE_ASSERT(display != EGL_NO_DISPLAY); DE_ASSERT(display != EGL_NO_DISPLAY);
egl.getConfigAttrib(display, config, EGL_RED_SIZE, &redBits); egl.getConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisual);
egl.getConfigAttrib(display, config, EGL_GREEN_SIZE, &greenBits);
egl.getConfigAttrib(display, config, EGL_BLUE_SIZE, &blueBits);
egl.getConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaBits);
EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()"); EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");
bitSum = redBits + greenBits + blueBits + alphaBits;
return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(), return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
width, height, bitSum); width, height, nativeVisual);
} }
eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay, eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
...@@ -364,8 +363,15 @@ ANGLENativeDisplayFactory::ANGLENativeDisplayFactory( ...@@ -364,8 +363,15 @@ ANGLENativeDisplayFactory::ANGLENativeDisplayFactory(
kDisplayCapabilities, kDisplayCapabilities,
EGL_PLATFORM_ANGLE_ANGLE, EGL_PLATFORM_ANGLE_ANGLE,
"EGL_EXT_platform_base"), "EGL_EXT_platform_base"),
mNativeDisplay(bitCast<eglw::EGLNativeDisplayType>(EGL_DEFAULT_DISPLAY)),
mPlatformAttributes(std::move(platformAttributes)) mPlatformAttributes(std::move(platformAttributes))
{ {
#if (DE_OS == DE_OS_UNIX)
// Make sure to only open the X display once so that it can be used by the EGL display as well
// as pixmaps
mNativeDisplay = bitCast<eglw::EGLNativeDisplayType>(XOpenDisplay(nullptr));
#endif // (DE_OS == DE_OS_UNIX)
m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState)); m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState));
m_nativePixmapRegistry.registerFactory(new NativePixmapFactory()); m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());
} }
...@@ -376,7 +382,8 @@ eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay( ...@@ -376,7 +382,8 @@ eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay(
const eglw::EGLAttrib *attribList) const const eglw::EGLAttrib *attribList) const
{ {
DE_UNREF(attribList); DE_UNREF(attribList);
return new ANGLENativeDisplay(mPlatformAttributes); return new ANGLENativeDisplay(bitCast<EGLNativeDisplayType>(mNativeDisplay),
mPlatformAttributes);
} }
} // namespace tcu } // namespace tcu
...@@ -51,6 +51,7 @@ class ANGLENativeDisplayFactory : public eglu::NativeDisplayFactory ...@@ -51,6 +51,7 @@ class ANGLENativeDisplayFactory : public eglu::NativeDisplayFactory
eglu::NativeDisplay *createDisplay(const eglw::EGLAttrib *attribList) const override; eglu::NativeDisplay *createDisplay(const eglw::EGLAttrib *attribList) const override;
private: private:
eglw::EGLNativeDisplayType mNativeDisplay;
std::vector<eglw::EGLAttrib> mPlatformAttributes; std::vector<eglw::EGLAttrib> mPlatformAttributes;
}; };
......
...@@ -57,14 +57,23 @@ class EGLBackwardsCompatibleContextTest : public ANGLETest ...@@ -57,14 +57,23 @@ class EGLBackwardsCompatibleContextTest : public ANGLETest
break; break;
} }
} }
if (!mConfig)
{
mConfig = configs[0];
}
ASSERT_NE(nullptr, mConfig); ASSERT_NE(nullptr, mConfig);
EGLint surfaceType = EGL_NONE;
eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
if (surfaceType & EGL_PBUFFER_BIT)
{
const EGLint pbufferAttribs[] = { const EGLint pbufferAttribs[] = {
EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE, EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,
}; };
mPbuffer = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttribs); mPbuffer = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttribs);
EXPECT_TRUE(mPbuffer != EGL_NO_SURFACE); EXPECT_TRUE(mPbuffer != EGL_NO_SURFACE);
} }
}
void testTearDown() override void testTearDown() override
{ {
...@@ -95,6 +104,7 @@ TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleDisbled) ...@@ -95,6 +104,7 @@ TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleDisbled)
{ {
ANGLE_SKIP_TEST_IF( ANGLE_SKIP_TEST_IF(
!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible"));
ANGLE_SKIP_TEST_IF(!mPbuffer);
std::pair<EGLint, EGLint> testVersions[] = { std::pair<EGLint, EGLint> testVersions[] = {
{1, 0}, {1, 1}, {2, 0}, {3, 0}, {3, 1}, {3, 2}, {1, 0}, {1, 1}, {2, 0}, {3, 0}, {3, 1}, {3, 2},
...@@ -133,6 +143,7 @@ TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleEnabledES3) ...@@ -133,6 +143,7 @@ TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleEnabledES3)
{ {
ANGLE_SKIP_TEST_IF( ANGLE_SKIP_TEST_IF(
!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible"));
ANGLE_SKIP_TEST_IF(!mPbuffer);
EGLint es3ContextAttribs[] = { EGLint es3ContextAttribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE, EGL_NONE}; EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE, EGL_NONE};
...@@ -162,6 +173,7 @@ TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleEnabledES1) ...@@ -162,6 +173,7 @@ TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleEnabledES1)
{ {
ANGLE_SKIP_TEST_IF( ANGLE_SKIP_TEST_IF(
!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible"));
ANGLE_SKIP_TEST_IF(!mPbuffer);
EGLint es11ContextAttribs[] = { EGLint es11ContextAttribs[] = {
EGL_CONTEXT_MAJOR_VERSION, 1, EGL_CONTEXT_MINOR_VERSION, 1, EGL_NONE, EGL_NONE}; EGL_CONTEXT_MAJOR_VERSION, 1, EGL_CONTEXT_MINOR_VERSION, 1, EGL_NONE, EGL_NONE};
......
...@@ -32,8 +32,6 @@ class EGLQueryContextTest : public ANGLETest ...@@ -32,8 +32,6 @@ class EGLQueryContextTest : public ANGLETest
8, 8,
EGL_RENDERABLE_TYPE, EGL_RENDERABLE_TYPE,
clientVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, clientVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE,
EGL_PBUFFER_BIT,
EGL_NONE}; EGL_NONE};
EXPECT_TRUE(eglChooseConfig(mDisplay, cfgattrs, &mConfig, 1, &ncfg) != EGL_FALSE); EXPECT_TRUE(eglChooseConfig(mDisplay, cfgattrs, &mConfig, 1, &ncfg) != EGL_FALSE);
EXPECT_TRUE(ncfg == 1); EXPECT_TRUE(ncfg == 1);
...@@ -42,10 +40,15 @@ class EGLQueryContextTest : public ANGLETest ...@@ -42,10 +40,15 @@ class EGLQueryContextTest : public ANGLETest
mContext = eglCreateContext(mDisplay, mConfig, nullptr, ctxattrs); mContext = eglCreateContext(mDisplay, mConfig, nullptr, ctxattrs);
EXPECT_TRUE(mContext != EGL_NO_CONTEXT); EXPECT_TRUE(mContext != EGL_NO_CONTEXT);
EGLint surfaceType = EGL_NONE;
eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
if (surfaceType & EGL_PBUFFER_BIT)
{
EGLint surfattrs[] = {EGL_WIDTH, 16, EGL_HEIGHT, 16, EGL_NONE}; EGLint surfattrs[] = {EGL_WIDTH, 16, EGL_HEIGHT, 16, EGL_NONE};
mSurface = eglCreatePbufferSurface(mDisplay, mConfig, surfattrs); mSurface = eglCreatePbufferSurface(mDisplay, mConfig, surfattrs);
EXPECT_TRUE(mSurface != EGL_NO_SURFACE); EXPECT_TRUE(mSurface != EGL_NO_SURFACE);
} }
}
void testTearDown() override void testTearDown() override
{ {
...@@ -53,16 +56,19 @@ class EGLQueryContextTest : public ANGLETest ...@@ -53,16 +56,19 @@ class EGLQueryContextTest : public ANGLETest
{ {
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext); eglDestroyContext(mDisplay, mContext);
if (mSurface)
{
eglDestroySurface(mDisplay, mSurface); eglDestroySurface(mDisplay, mSurface);
}
eglTerminate(mDisplay); eglTerminate(mDisplay);
} }
ASSERT_EGL_SUCCESS() << "Error during test TearDown"; ASSERT_EGL_SUCCESS() << "Error during test TearDown";
} }
EGLDisplay mDisplay; EGLDisplay mDisplay = EGL_NO_DISPLAY;
EGLConfig mConfig; EGLConfig mConfig = EGL_NO_CONFIG_KHR;
EGLContext mContext; EGLContext mContext = EGL_NO_CONTEXT;
EGLSurface mSurface; EGLSurface mSurface = EGL_NO_SURFACE;
}; };
TEST_P(EGLQueryContextTest, GetConfigID) TEST_P(EGLQueryContextTest, GetConfigID)
...@@ -98,6 +104,8 @@ TEST_P(EGLQueryContextTest, GetRenderBufferNoSurface) ...@@ -98,6 +104,8 @@ TEST_P(EGLQueryContextTest, GetRenderBufferNoSurface)
TEST_P(EGLQueryContextTest, GetRenderBufferBoundSurface) TEST_P(EGLQueryContextTest, GetRenderBufferBoundSurface)
{ {
ANGLE_SKIP_TEST_IF(!mSurface);
EGLint renderBuffer, contextRenderBuffer; EGLint renderBuffer, contextRenderBuffer;
EXPECT_TRUE(eglQuerySurface(mDisplay, mSurface, EGL_RENDER_BUFFER, &renderBuffer) != EGL_FALSE); EXPECT_TRUE(eglQuerySurface(mDisplay, mSurface, EGL_RENDER_BUFFER, &renderBuffer) != EGL_FALSE);
EXPECT_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) != EGL_FALSE); EXPECT_TRUE(eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) != EGL_FALSE);
......
...@@ -133,14 +133,22 @@ class EGLSurfaceTest : public ANGLETest ...@@ -133,14 +133,22 @@ class EGLSurfaceTest : public ANGLETest
{ {
mConfig = config; mConfig = config;
EGLint surfaceType = EGL_NONE;
eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);
std::vector<EGLint> windowAttributes; std::vector<EGLint> windowAttributes;
windowAttributes.push_back(EGL_NONE); windowAttributes.push_back(EGL_NONE);
if (surfaceType & EGL_WINDOW_BIT)
{
// Create first window surface // Create first window surface
mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),
windowAttributes.data()); windowAttributes.data());
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
}
if (surfaceType & EGL_PBUFFER_BIT)
{
// Give pbuffer non-zero dimensions. // Give pbuffer non-zero dimensions.
std::vector<EGLint> pbufferAttributes; std::vector<EGLint> pbufferAttributes;
pbufferAttributes.push_back(EGL_WIDTH); pbufferAttributes.push_back(EGL_WIDTH);
...@@ -151,6 +159,8 @@ class EGLSurfaceTest : public ANGLETest ...@@ -151,6 +159,8 @@ class EGLSurfaceTest : public ANGLETest
mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttributes.data()); mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttributes.data());
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
}
initializeContext(); initializeContext();
} }
...@@ -378,6 +388,7 @@ TEST_P(EGLSurfaceTest, MessageLoopBugContext) ...@@ -378,6 +388,7 @@ TEST_P(EGLSurfaceTest, MessageLoopBugContext)
initializeDisplay(); initializeDisplay();
initializeSurfaceWithDefaultConfig(); initializeSurfaceWithDefaultConfig();
ANGLE_SKIP_TEST_IF(!mPbufferSurface);
runMessageLoopTest(mPbufferSurface, mSecondContext); runMessageLoopTest(mPbufferSurface, mSecondContext);
} }
......
...@@ -48,9 +48,16 @@ class EGLSurfacelessContextTest : public ANGLETest ...@@ -48,9 +48,16 @@ class EGLSurfacelessContextTest : public ANGLETest
if (surfaceType & EGL_PBUFFER_BIT) if (surfaceType & EGL_PBUFFER_BIT)
{ {
mConfig = config; mConfig = config;
mSupportsPbuffers = true;
break; break;
} }
} }
if (!mConfig)
{
mConfig = configs[0];
}
ASSERT_NE(nullptr, mConfig); ASSERT_NE(nullptr, mConfig);
} }
...@@ -83,6 +90,11 @@ class EGLSurfacelessContextTest : public ANGLETest ...@@ -83,6 +90,11 @@ class EGLSurfacelessContextTest : public ANGLETest
EGLSurface createPbuffer(int width, int height) EGLSurface createPbuffer(int width, int height)
{ {
if (!mSupportsPbuffers)
{
return EGL_NO_SURFACE;
}
const EGLint pbufferAttribs[] = { const EGLint pbufferAttribs[] = {
EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE, EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,
}; };
...@@ -118,6 +130,7 @@ class EGLSurfacelessContextTest : public ANGLETest ...@@ -118,6 +130,7 @@ class EGLSurfacelessContextTest : public ANGLETest
EGLContext mContext = EGL_NO_CONTEXT; EGLContext mContext = EGL_NO_CONTEXT;
EGLSurface mPbuffer = EGL_NO_SURFACE; EGLSurface mPbuffer = EGL_NO_SURFACE;
bool mSupportsPbuffers = false;
EGLConfig mConfig = 0; EGLConfig mConfig = 0;
EGLDisplay mDisplay = EGL_NO_DISPLAY; EGLDisplay mDisplay = EGL_NO_DISPLAY;
}; };
...@@ -214,10 +227,8 @@ TEST_P(EGLSurfacelessContextTest, ClearReadPixelsInFBO) ...@@ -214,10 +227,8 @@ TEST_P(EGLSurfacelessContextTest, ClearReadPixelsInFBO)
// Test clear+readpixels in an FBO in surfaceless and in the default FBO in a pbuffer // Test clear+readpixels in an FBO in surfaceless and in the default FBO in a pbuffer
TEST_P(EGLSurfacelessContextTest, Switcheroo) TEST_P(EGLSurfacelessContextTest, Switcheroo)
{ {
if (!checkExtension()) ANGLE_SKIP_TEST_IF(!checkExtension());
{ ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
return;
}
EGLContext context = createContext(); EGLContext context = createContext();
EGLSurface pbuffer = createPbuffer(500, 500); EGLSurface pbuffer = createPbuffer(500, 500);
......
...@@ -107,17 +107,17 @@ TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear) ...@@ -107,17 +107,17 @@ TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear)
ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr)); ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr));
// While this is not required by the extension, test that our implementation returns only one
// config, with the same native visual Id that we provided.
int nConfigs = 0; int nConfigs = 0;
ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, nullptr, 0, &nConfigs)); ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, nullptr, 0, &nConfigs));
ASSERT_EQ(1, nConfigs); ASSERT_GE(nConfigs, 1);
int nReturnedConfigs = 0; int nReturnedConfigs = 0;
EGLConfig config; std::vector<EGLConfig> configs(nConfigs);
ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, &config, 1, &nReturnedConfigs)); ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, configs.data(), nConfigs, &nReturnedConfigs));
ASSERT_EQ(nConfigs, nReturnedConfigs); ASSERT_EQ(nConfigs, nReturnedConfigs);
for (EGLConfig config : configs)
{
EGLint eglNativeId; EGLint eglNativeId;
ASSERT_TRUE(EGL_TRUE == ASSERT_TRUE(EGL_TRUE ==
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &eglNativeId)); eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &eglNativeId));
...@@ -145,6 +145,7 @@ TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear) ...@@ -145,6 +145,7 @@ TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear)
eglDestroyContext(display, context); eglDestroyContext(display, context);
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
}
OSWindow::Delete(&osWindow); OSWindow::Delete(&osWindow);
......
...@@ -95,15 +95,18 @@ class PbufferTest : public ANGLETest ...@@ -95,15 +95,18 @@ class PbufferTest : public ANGLETest
{ {
glDeleteProgram(mTextureProgram); glDeleteProgram(mTextureProgram);
if (mPbuffer)
{
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
eglDestroySurface(window->getDisplay(), mPbuffer); eglDestroySurface(window->getDisplay(), mPbuffer);
} }
}
GLuint mTextureProgram; GLuint mTextureProgram;
GLint mTextureUniformLocation; GLint mTextureUniformLocation;
const size_t mPbufferSize = 32; const size_t mPbufferSize = 32;
EGLSurface mPbuffer; EGLSurface mPbuffer = EGL_NO_SURFACE;
bool mSupportsPbuffers; bool mSupportsPbuffers;
bool mSupportsBindTexImage; bool mSupportsBindTexImage;
}; };
...@@ -122,7 +125,7 @@ TEST_P(PbufferTest, Clearing) ...@@ -122,7 +125,7 @@ TEST_P(PbufferTest, Clearing)
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255); EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
// Apply the Pbuffer and clear it to purple and verify // Apply the Pbuffer and clear it to purple and verify
eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext()); eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
...@@ -159,8 +162,8 @@ TEST_P(PbufferTest, BindTexImage) ...@@ -159,8 +162,8 @@ TEST_P(PbufferTest, BindTexImage)
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255, EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(mPbufferSize) / 2,
0, 255, 255); static_cast<GLint>(mPbufferSize) / 2, GLColor::magenta);
// Apply the window surface // Apply the window surface
window->makeCurrent(); window->makeCurrent();
......
//
// Copyright 2020 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 "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "util/EGLWindow.h"
#include "util/OSPixmap.h"
#include "util/OSWindow.h"
#include <iostream>
using namespace angle;
class PixmapTest : public ANGLETest
{
protected:
PixmapTest()
{
setWindowWidth(512);
setWindowHeight(512);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void testSetUp() override
{
mTextureProgram =
CompileProgram(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
if (mTextureProgram == 0)
{
FAIL() << "shader compilation failed.";
}
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "u_tex2D");
ASSERT_NE(-1, mTextureUniformLocation);
EGLWindow *window = getEGLWindow();
EGLint surfaceType = 0;
eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE,
&surfaceType);
mSupportsPixmaps = (surfaceType & EGL_PIXMAP_BIT) != 0;
EGLint bindToTextureRGBA = 0;
eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA,
&bindToTextureRGBA);
mSupportsBindTexImage =
IsEGLDisplayExtensionEnabled(window->getDisplay(), "EGL_NOK_texture_from_pixmap") &&
(bindToTextureRGBA == EGL_TRUE);
if (mSupportsPixmaps)
{
mOSPixmap.reset(CreateOSPixmap());
OSWindow *osWindow = getOSWindow();
EGLint nativeVisual = 0;
ASSERT_TRUE(eglGetConfigAttrib(window->getDisplay(), window->getConfig(),
EGL_NATIVE_VISUAL_ID, &nativeVisual));
ASSERT_TRUE(mOSPixmap->initialize(osWindow->getNativeDisplay(), mPixmapSize,
mPixmapSize, nativeVisual));
std::vector<EGLint> attribs;
if (mSupportsBindTexImage)
{
attribs.push_back(EGL_TEXTURE_FORMAT);
attribs.push_back(EGL_TEXTURE_RGBA);
attribs.push_back(EGL_TEXTURE_TARGET);
attribs.push_back(EGL_TEXTURE_2D);
}
attribs.push_back(EGL_NONE);
mPixmap = eglCreatePixmapSurface(window->getDisplay(), window->getConfig(),
mOSPixmap->getNativePixmap(), attribs.data());
ASSERT_NE(mPixmap, EGL_NO_SURFACE);
ASSERT_EGL_SUCCESS();
}
ASSERT_GL_NO_ERROR();
}
void testTearDown() override
{
glDeleteProgram(mTextureProgram);
if (mPixmap)
{
EGLWindow *window = getEGLWindow();
eglDestroySurface(window->getDisplay(), mPixmap);
}
mOSPixmap = nullptr;
}
GLuint mTextureProgram;
GLint mTextureUniformLocation;
std::unique_ptr<OSPixmap> mOSPixmap;
EGLSurface mPixmap = EGL_NO_SURFACE;
const size_t mPixmapSize = 32;
bool mSupportsPixmaps;
bool mSupportsBindTexImage;
};
// Test clearing a Pixmap and checking the color is correct
TEST_P(PixmapTest, Clearing)
{
ANGLE_SKIP_TEST_IF(!mSupportsPixmaps);
EGLWindow *window = getEGLWindow();
// Clear the window surface to blue and verify
window->makeCurrent();
ASSERT_EGL_SUCCESS();
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
// Apply the Pixmap and clear it to purple and verify
eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
ASSERT_EGL_SUCCESS();
glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
0, 255, 255);
// Rebind the window surface and verify that it is still blue
window->makeCurrent();
ASSERT_EGL_SUCCESS();
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
}
// Bind the Pixmap to a texture and verify it renders correctly
TEST_P(PixmapTest, BindTexImage)
{
// Test skipped because pixmaps are not supported or pixmaps do not support binding to RGBA
// textures.
ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
// This test fails flakily on Linux intel when run with many other tests.
ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
EGLWindow *window = getEGLWindow();
// Apply the Pixmap and clear it to purple
eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
ASSERT_EGL_SUCCESS();
glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
0, 255, 255);
// Apply the window surface
window->makeCurrent();
// Create a texture and bind the pixmap to it
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
EXPECT_GL_NO_ERROR();
eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
glViewport(0, 0, getWindowWidth(), getWindowHeight());
ASSERT_EGL_SUCCESS();
// Draw a quad and verify that it is purple
glUseProgram(mTextureProgram);
glUniform1i(mTextureUniformLocation, 0);
drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
EXPECT_GL_NO_ERROR();
// Unbind the texture
eglReleaseTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
ASSERT_EGL_SUCCESS();
// Verify that purple was drawn
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
glDeleteTextures(1, &texture);
}
// Bind a Pixmap, redefine the texture, and verify it renders correctly
TEST_P(PixmapTest, BindTexImageAndRedefineTexture)
{
// Test skipped because pixmaps are not supported or Pixmaps do not support binding to RGBA
// textures.
ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
EGLWindow *window = getEGLWindow();
// Apply the Pixmap and clear it to purple
eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
ASSERT_EGL_SUCCESS();
glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
0, 255, 255);
// Apply the window surface
window->makeCurrent();
// Create a texture and bind the Pixmap to it
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
EXPECT_GL_NO_ERROR();
eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
glViewport(0, 0, getWindowWidth(), getWindowHeight());
ASSERT_EGL_SUCCESS();
// Redefine the texture
unsigned int pixelValue = 0xFFFF00FF;
std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, &pixelData[0]);
// Draw a quad and verify that it is magenta
glUseProgram(mTextureProgram);
glUniform1i(mTextureUniformLocation, 0);
drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
EXPECT_GL_NO_ERROR();
// Verify that magenta was drawn
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
glDeleteTextures(1, &texture);
}
ANGLE_INSTANTIATE_TEST_ES2(PixmapTest);
...@@ -106,7 +106,7 @@ void EGLMakeCurrentPerfTest::SetUp() ...@@ -106,7 +106,7 @@ void EGLMakeCurrentPerfTest::SetUp()
EGL_RENDERABLE_TYPE, EGL_RENDERABLE_TYPE,
GetParam().majorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, GetParam().majorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_SURFACE_TYPE,
EGL_PBUFFER_BIT, EGL_WINDOW_BIT,
EGL_NONE}; EGL_NONE};
ASSERT_TRUE(eglChooseConfig(mDisplay, configAttrs, &mConfig, 1, &numConfigs)); ASSERT_TRUE(eglChooseConfig(mDisplay, configAttrs, &mConfig, 1, &numConfigs));
......
...@@ -51,6 +51,8 @@ if (angle_use_x11) { ...@@ -51,6 +51,8 @@ if (angle_use_x11) {
if (is_fuchsia) { if (is_fuchsia) {
_util_sources += [ _util_sources += [
"fuchsia/FuchsiaPixmap.cpp",
"fuchsia/FuchsiaPixmap.h",
"fuchsia/ScenicWindow.cpp", "fuchsia/ScenicWindow.cpp",
"fuchsia/ScenicWindow.h", "fuchsia/ScenicWindow.h",
] ]
......
...@@ -26,7 +26,7 @@ class ANGLE_UTIL_EXPORT OSPixmap ...@@ -26,7 +26,7 @@ class ANGLE_UTIL_EXPORT OSPixmap
virtual bool initialize(EGLNativeDisplayType display, virtual bool initialize(EGLNativeDisplayType display,
size_t width, size_t width,
size_t height, size_t height,
int depth) = 0; int nativeVisual) = 0;
virtual EGLNativePixmapType getNativePixmap() const = 0; virtual EGLNativePixmapType getNativePixmap() const = 0;
}; };
......
//
// Copyright 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.
//
// FuchsiaPixmap.cpp: Implementation of OSPixmap for Fuchsia
#include "util/fuchsia/FuchsiaPixmap.h"
OSPixmap *CreateOSPixmap()
{
return nullptr;
}
//
// Copyright 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.
//
// FuchsiaPixmap.h: Definition of the implementation of OSPixmap for Fuchsia
#ifndef UTIL_FUCHSIA_FUCHSIAPIXMAP_H_
#define UTIL_FUCHSIA_FUCHSIAPIXMAP_H_
#include "util/OSPixmap.h"
#endif // UTIL_FUCHSIA_FUCHSIAPIXMAP_H_
...@@ -18,12 +18,27 @@ X11Pixmap::~X11Pixmap() ...@@ -18,12 +18,27 @@ X11Pixmap::~X11Pixmap()
} }
} }
bool X11Pixmap::initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) bool X11Pixmap::initialize(EGLNativeDisplayType display,
size_t width,
size_t height,
int nativeVisual)
{ {
mDisplay = display; mDisplay = display;
int screen = DefaultScreen(mDisplay); int screen = DefaultScreen(mDisplay);
Window root = RootWindow(mDisplay, screen); Window root = RootWindow(mDisplay, screen);
int depth = 0;
XVisualInfo visualTemplate;
visualTemplate.visualid = nativeVisual;
int numVisuals = 0;
XVisualInfo *info = XGetVisualInfo(mDisplay, VisualIDMask, &visualTemplate, &numVisuals);
if (numVisuals == 1)
{
depth = info->depth;
}
XFree(info);
mPixmap = XCreatePixmap(mDisplay, root, static_cast<unsigned int>(width), mPixmap = XCreatePixmap(mDisplay, root, static_cast<unsigned int>(width),
static_cast<unsigned int>(height), depth); static_cast<unsigned int>(height), depth);
......
...@@ -20,7 +20,10 @@ class X11Pixmap : public OSPixmap ...@@ -20,7 +20,10 @@ class X11Pixmap : public OSPixmap
X11Pixmap(); X11Pixmap();
~X11Pixmap() override; ~X11Pixmap() override;
bool initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) override; bool initialize(EGLNativeDisplayType display,
size_t width,
size_t height,
int nativeVisual) override;
EGLNativePixmapType getNativePixmap() const override; EGLNativePixmapType getNativePixmap() const override;
......
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