Commit 701b74b0 by Ian Ewell

Add support for EGL_KHR_stream.

EGL_KHR_stream is now implemented. Since the extension does not come with any producers or consumers, it does not have much functionality and the implementation is therefore very simple (validation layers and a new object to store some attributes). This however add the groundwork to add the appropriate consumer and producer extensions to stream D3D NV12 textures directly into ANGLE which will significantly improve video performance on Chromium on D3D-based platforms. BUG=angleproject:1332 Change-Id: Ie240c73869f5098d1215cc5e27aa5decd06c3ed1 Reviewed-on: https://chromium-review.googlesource.com/330003 Commit-Queue: Ian Ewell <ewell@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent bb51c35c
......@@ -635,7 +635,8 @@ DisplayExtensions::DisplayExtensions()
getAllProcAddresses(false),
flexibleSurfaceCompatibility(false),
directComposition(false),
createContextNoError(false)
createContextNoError(false),
stream(false)
{
}
......@@ -664,6 +665,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
......
......@@ -482,6 +482,9 @@ struct DisplayExtensions
// KHR_create_context_no_error
bool createContextNoError;
// EGL_KHR_stream
bool stream;
};
struct DeviceExtensions
......
......@@ -28,6 +28,7 @@
#include "libANGLE/histogram_macros.h"
#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Stream.h"
#include "libANGLE/renderer/DisplayImpl.h"
#include "libANGLE/renderer/ImageImpl.h"
#include "third_party/trace_event/trace_event.h"
......@@ -299,6 +300,7 @@ Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDe
mAttributeMap(),
mConfigSet(),
mContextSet(),
mStreamSet(),
mInitialized(false),
mCaps(),
mDisplayExtensions(),
......@@ -438,6 +440,11 @@ void Display::terminate()
destroyImage(*mImageSet.begin());
}
while (!mStreamSet.empty())
{
destroyStream(*mStreamSet.begin());
}
while (!mImplementation->getSurfaceSet().empty())
{
destroySurface(*mImplementation->getSurfaceSet().begin());
......@@ -699,6 +706,24 @@ Error Display::createImage(gl::Context *context,
return egl::Error(EGL_SUCCESS);
}
Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
{
ASSERT(isInitialized());
rx::StreamImpl *streamImpl = mImplementation->createStream(attribs);
ASSERT(streamImpl != nullptr);
Stream *stream = new Stream(streamImpl, attribs);
ASSERT(stream != nullptr);
mStreamSet.insert(stream);
ASSERT(outStream != nullptr);
*outStream = stream;
return Error(EGL_SUCCESS);
}
Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
gl::Context **outContext)
{
......@@ -788,6 +813,12 @@ void Display::destroyImage(egl::Image *image)
mImageSet.erase(iter);
}
void Display::destroyStream(egl::Stream *stream)
{
mStreamSet.erase(stream);
SafeDelete(stream);
}
void Display::destroyContext(gl::Context *context)
{
mContextSet.erase(context);
......@@ -854,6 +885,11 @@ bool Display::isValidImage(const Image *image) const
return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
}
bool Display::isValidStream(const Stream *stream) const
{
return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
}
bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
{
WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
......
......@@ -35,6 +35,7 @@ namespace egl
class Device;
class Image;
class Surface;
class Stream;
class Display final : angle::NonCopyable
{
......@@ -67,6 +68,8 @@ class Display final : angle::NonCopyable
const AttributeMap &attribs,
Image **outImage);
Error createStream(const AttributeMap &attribs, Stream **outStream);
Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
gl::Context **outContext);
......@@ -74,6 +77,7 @@ class Display final : angle::NonCopyable
void destroySurface(egl::Surface *surface);
void destroyImage(egl::Image *image);
void destroyStream(egl::Stream *stream);
void destroyContext(gl::Context *context);
bool isInitialized() const;
......@@ -81,6 +85,7 @@ class Display final : angle::NonCopyable
bool isValidContext(gl::Context *context) const;
bool isValidSurface(egl::Surface *surface) const;
bool isValidImage(const Image *image) const;
bool isValidStream(const Stream *stream) const;
bool isValidNativeWindow(EGLNativeWindowType window) const;
static bool isValidDisplay(const egl::Display *display);
......@@ -130,6 +135,9 @@ class Display final : angle::NonCopyable
typedef std::set<Image *> ImageSet;
ImageSet mImageSet;
typedef std::set<Stream *> StreamSet;
StreamSet mStreamSet;
bool mInitialized;
Caps mCaps;
......
//
// Copyright (c) 2016 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.
//
// Stream.cpp: Implements the egl::Stream class, representing the stream
// where frames are streamed in. Implements EGLStreanKHR.
#include "libANGLE/Stream.h"
#include <platform/Platform.h>
#include <EGL/eglext.h>
#include "common/debug.h"
#include "common/mathutil.h"
#include "common/platform.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/StreamImpl.h"
namespace egl
{
Stream::Stream(rx::StreamImpl *impl, const AttributeMap &attribs)
: mImplementation(impl),
mState(EGL_STREAM_STATE_CREATED_KHR),
mProducerFrame(0),
mConsumerFrame(0),
mConsumerLatency(attribs.get(EGL_CONSUMER_LATENCY_USEC_KHR, 0))
{
}
Stream::~Stream()
{
SafeDelete(mImplementation);
}
void Stream::setConsumerLatency(EGLint latency)
{
mConsumerLatency = latency;
}
EGLint Stream::getConsumerLatency() const
{
return mConsumerLatency;
}
EGLuint64KHR Stream::getProducerFrame() const
{
return mProducerFrame;
}
EGLuint64KHR Stream::getConsumerFrame() const
{
return mConsumerFrame;
}
EGLenum Stream::getState() const
{
return mState;
}
} // namespace egl
//
// Copyright (c) 2016 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.
//
// Stream.h: Defines the egl::Stream class, representing the stream
// where frames are streamed in. Implements EGLStreanKHR.
#ifndef LIBANGLE_STREAM_H_
#define LIBANGLE_STREAM_H_
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
namespace rx
{
class StreamImpl;
}
namespace egl
{
class Stream final : angle::NonCopyable
{
public:
Stream(rx::StreamImpl *impl, const AttributeMap &attribs);
~Stream();
EGLenum getState() const;
void setConsumerLatency(EGLint latency);
EGLint getConsumerLatency() const;
EGLuint64KHR getProducerFrame() const;
EGLuint64KHR getConsumerFrame() const;
private:
// Implementation
rx::StreamImpl *mImplementation;
// EGL defined attributes
EGLint mState;
EGLuint64KHR mProducerFrame;
EGLuint64KHR mConsumerFrame;
EGLint mConsumerLatency;
};
} // namespace egl
#endif // LIBANGLE_STREAM_H_
......@@ -38,6 +38,7 @@ class SurfaceImpl;
class ImageImpl;
struct ConfigDesc;
class DeviceImpl;
class StreamImpl;
class DisplayImpl : angle::NonCopyable
{
......@@ -68,6 +69,8 @@ class DisplayImpl : angle::NonCopyable
const gl::Context *shareContext,
const egl::AttributeMap &attribs) = 0;
virtual StreamImpl *createStream(const egl::AttributeMap &attribs) = 0;
virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0;
virtual egl::ConfigSet generateConfigs() const = 0;
......
......@@ -30,6 +30,7 @@ class ShaderImpl;
class TextureImpl;
class TransformFeedbackImpl;
class VertexArrayImpl;
class StreamImpl;
class ImplFactory : angle::NonCopyable
{
......
//
// Copyright (c) 2016 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.
//
// StreamImpl.h: Defines the abstract rx::StreamImpl class.
#ifndef LIBANGLE_RENDERER_STREAMIMPL_H_
#define LIBANGLE_RENDERER_STREAMIMPL_H_
#include "common/angleutils.h"
namespace rx
{
class StreamImpl : angle::NonCopyable
{
public:
explicit StreamImpl() {}
virtual ~StreamImpl() {}
};
} // namespace rx
#endif // LIBANGLE_RENDERER_STREAMIMPL_H_
......@@ -237,6 +237,12 @@ gl::Context *DisplayD3D::createContext(const egl::Config *config,
return new gl::Context(config, shareContext, mRenderer, attribs);
}
StreamImpl *DisplayD3D::createStream(const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
return mRenderer->createStream(attribs);
}
egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
{
return egl::Error(EGL_SUCCESS);
......
......@@ -45,6 +45,8 @@ class DisplayD3D : public DisplayImpl
const gl::Context *shareContext,
const egl::AttributeMap &attribs) override;
StreamImpl *createStream(const egl::AttributeMap &attribs) override;
egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
egl::ConfigSet generateConfigs() const override;
......
......@@ -265,6 +265,9 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
bool presentPathFastEnabled() const { return mPresentPathFastEnabled; }
// Stream creation
virtual StreamImpl *createStream(const egl::AttributeMap &attribs) = 0;
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 0;
......
......@@ -36,6 +36,7 @@
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
#include "libANGLE/renderer/d3d/d3d11/Stream11.h"
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
......@@ -1027,6 +1028,8 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->glTextureCubemapImage = true;
outExtensions->glRenderbufferImage = true;
outExtensions->stream = true;
outExtensions->flexibleSurfaceCompatibility = true;
outExtensions->directComposition = !!mDCompModule;
}
......@@ -3498,6 +3501,11 @@ TransformFeedbackImpl* Renderer11::createTransformFeedback()
return new TransformFeedbackD3D();
}
StreamImpl *Renderer11::createStream(const egl::AttributeMap &attribs)
{
return new Stream11(this);
}
bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
{
ASSERT(getRendererExtensions().pixelBufferObject);
......
......@@ -239,6 +239,9 @@ class Renderer11 : public RendererD3D
// Transform Feedback creation
virtual TransformFeedbackImpl* createTransformFeedback();
// Stream Creation
StreamImpl *createStream(const egl::AttributeMap &attribs) override;
// D3D11-renderer specific methods
ID3D11Device *getDevice() { return mDevice; }
void *getD3DDevice() override;
......
//
// Copyright (c) 2016 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.
//
// Stream11.cpp: Defines the rx::Stream11 class which implements rx::StreamImpl.
#include "libANGLE/renderer/d3d/d3d11/Stream11.h"
#include "common/utilities.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace rx
{
Stream11::Stream11(Renderer11 *renderer) : mRenderer(renderer)
{
}
Stream11::~Stream11()
{
}
} // namespace rx
//
// Copyright (c) 2016 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.
//
// Stream11.h: Defines the rx::Stream11 class which implements rx::StreamImpl.
#ifndef LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
#include "libANGLE/renderer/StreamImpl.h"
namespace rx
{
class Renderer11;
class Stream11 : public StreamImpl
{
public:
Stream11(Renderer11 *renderer);
~Stream11() override;
private:
Renderer11 *mRenderer;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
......@@ -770,6 +770,13 @@ TransformFeedbackImpl* Renderer9::createTransformFeedback()
return new TransformFeedbackD3D();
}
StreamImpl *Renderer9::createStream(const egl::AttributeMap &attribs)
{
// Streams are not supported under D3D9
UNREACHABLE();
return nullptr;
}
bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
{
// Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
......
......@@ -237,6 +237,9 @@ class Renderer9 : public RendererD3D
// Transform Feedback creation
virtual TransformFeedbackImpl* createTransformFeedback();
// Stream Creation
StreamImpl *createStream(const egl::AttributeMap &attribs) override;
// Buffer-to-texture and Texture-to-buffer copies
virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
......
......@@ -63,6 +63,12 @@ gl::Context *DisplayGL::createContext(const egl::Config *config,
return new gl::Context(config, shareContext, mRenderer, attribs);
}
StreamImpl *DisplayGL::createStream(const egl::AttributeMap &attribs)
{
UNREACHABLE();
return nullptr;
}
egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
{
if (!drawSurface)
......
......@@ -34,6 +34,8 @@ class DisplayGL : public DisplayImpl
const gl::Context *shareContext,
const egl::AttributeMap &attribs) override;
StreamImpl *createStream(const egl::AttributeMap &attribs) override;
egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
virtual egl::Error getDriverVersion(std::string *version) const = 0;
......
......@@ -14,6 +14,7 @@
#include "libANGLE/Device.h"
#include "libANGLE/Display.h"
#include "libANGLE/Image.h"
#include "libANGLE/Stream.h"
#include "libANGLE/Surface.h"
#include <EGL/eglext.h>
......@@ -176,6 +177,28 @@ Error ValidateImage(const Display *display, const Image *image)
return Error(EGL_SUCCESS);
}
Error ValidateStream(const Display *display, const Stream *stream)
{
Error error = ValidateDisplay(display);
if (error.isError())
{
return error;
}
const DisplayExtensions &displayExtensions = display->getExtensions();
if (!displayExtensions.stream)
{
return Error(EGL_BAD_ACCESS, "Stream extension not active");
}
if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
{
return Error(EGL_BAD_STREAM_KHR, "Invalid stream");
}
return Error(GL_NO_ERROR);
}
Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
const AttributeMap& attributes)
{
......@@ -1054,4 +1077,136 @@ Error ValidateReleaseDeviceANGLE(Device *device)
return Error(EGL_SUCCESS);
}
Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes)
{
Error error = ValidateDisplay(display);
if (error.isError())
{
return error;
}
const DisplayExtensions &displayExtensions = display->getExtensions();
if (!displayExtensions.stream)
{
return Error(EGL_BAD_ALLOC, "Stream extension not active");
}
for (const auto &attributeIter : attributes)
{
EGLint attribute = attributeIter.first;
EGLint value = attributeIter.second;
switch (attribute)
{
case EGL_STREAM_STATE_KHR:
case EGL_PRODUCER_FRAME_KHR:
case EGL_CONSUMER_FRAME_KHR:
return Error(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
case EGL_CONSUMER_LATENCY_USEC_KHR:
// Technically not in spec but a latency < 0 makes no sense so we check it
if (value < 0)
{
return Error(EGL_BAD_PARAMETER, "Latency must be positive");
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
}
}
return Error(EGL_SUCCESS);
}
Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream)
{
Error error = ValidateStream(display, stream);
if (error.isError())
{
return error;
}
return Error(EGL_SUCCESS);
}
Error ValidateStreamAttribKHR(const Display *display,
const Stream *stream,
EGLint attribute,
EGLint value)
{
Error error = ValidateStream(display, stream);
if (error.isError())
{
return error;
}
if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
{
return Error(EGL_BAD_STATE_KHR, "Bad stream state");
}
switch (attribute)
{
case EGL_STREAM_STATE_KHR:
case EGL_PRODUCER_FRAME_KHR:
case EGL_CONSUMER_FRAME_KHR:
return Error(EGL_BAD_ACCESS, "Attribute is read only");
case EGL_CONSUMER_LATENCY_USEC_KHR:
if (value < 0)
{
return Error(EGL_BAD_PARAMETER, "Stream consumer latency must be positive");
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
}
return Error(EGL_SUCCESS);
}
Error ValidateQueryStreamKHR(const Display *display,
const Stream *stream,
EGLenum attribute,
EGLint *value)
{
Error error = ValidateStream(display, stream);
if (error.isError())
{
return error;
}
switch (attribute)
{
case EGL_STREAM_STATE_KHR:
case EGL_CONSUMER_LATENCY_USEC_KHR:
break;
default:
return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
}
return Error(EGL_SUCCESS);
}
Error ValidateQueryStreamu64KHR(const Display *display,
const Stream *stream,
EGLenum attribute,
EGLuint64KHR *value)
{
Error error = ValidateStream(display, stream);
if (error.isError())
{
return error;
}
switch (attribute)
{
case EGL_CONSUMER_FRAME_KHR:
case EGL_PRODUCER_FRAME_KHR:
break;
default:
return Error(EGL_BAD_ATTRIBUTE, "Invalid attribute");
}
return Error(EGL_SUCCESS);
}
}
......@@ -12,6 +12,7 @@
#include "libANGLE/Error.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
namespace gl
{
......@@ -26,6 +27,7 @@ struct Config;
class Device;
class Display;
class Image;
class Stream;
class Surface;
// Object validation
......@@ -58,6 +60,21 @@ Error ValidateCreateDeviceANGLE(EGLint device_type,
const EGLAttrib *attrib_list);
Error ValidateReleaseDeviceANGLE(Device *device);
Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes);
Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream);
Error ValidateStreamAttribKHR(const Display *display,
const Stream *stream,
EGLint attribute,
EGLint value);
Error ValidateQueryStreamKHR(const Display *display,
const Stream *stream,
EGLenum attribute,
EGLint *value);
Error ValidateQueryStreamu64KHR(const Display *display,
const Stream *stream,
EGLenum attribute,
EGLuint64KHR *value);
// Other validation
Error ValidateCompatibleConfigs(const Display *display,
const Config *config1,
......
......@@ -288,4 +288,37 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const cha
return egl::GetProcAddress(procname);
}
EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
{
return egl::CreateStreamKHR(dpy, attrib_list);
}
EGLBoolean EGLAPIENTRY eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
{
return egl::DestroyStreamKHR(dpy, stream);
}
EGLBoolean EGLAPIENTRY eglStreamAttribKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLint value)
{
return egl::StreamAttribKHR(dpy, stream, attribute, value);
}
EGLBoolean EGLAPIENTRY eglQueryStreamKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLint *value)
{
return egl::QueryStreamKHR(dpy, stream, attribute, value);
}
EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLuint64KHR *value)
{
return egl::QueryStreamu64KHR(dpy, stream, attribute, value);
}
}
......@@ -46,6 +46,11 @@ EXPORTS
eglDestroyImageKHR @52
eglCreateDeviceANGLE @53
eglReleaseDeviceANGLE @54
eglCreateStreamKHR @55
eglDestroyStreamKHR @56
eglStreamAttribKHR @57
eglQueryStreamKHR @58
eglQueryStreamu64KHR @59
; 1.5 entry points
eglCreateSync @38
......
......@@ -109,6 +109,8 @@
'libANGLE/Shader.h',
'libANGLE/State.cpp',
'libANGLE/State.h',
'libANGLE/Stream.cpp',
'libANGLE/Stream.h',
'libANGLE/Surface.cpp',
'libANGLE/Surface.h',
'libANGLE/Texture.cpp',
......@@ -151,6 +153,7 @@
'libANGLE/renderer/Renderer.h',
'libANGLE/renderer/SamplerImpl.h',
'libANGLE/renderer/ShaderImpl.h',
'libANGLE/renderer/StreamImpl.h',
'libANGLE/renderer/SurfaceImpl.cpp',
'libANGLE/renderer/SurfaceImpl.h',
'libANGLE/renderer/TextureImpl.h',
......@@ -378,6 +381,8 @@
'libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h',
'libANGLE/renderer/d3d/d3d11/StateManager11.cpp',
'libANGLE/renderer/d3d/d3d11/StateManager11.h',
'libANGLE/renderer/d3d/d3d11/Stream11.cpp',
'libANGLE/renderer/d3d/d3d11/Stream11.h',
'libANGLE/renderer/d3d/d3d11/SwapChain11.cpp',
'libANGLE/renderer/d3d/d3d11/SwapChain11.h',
'libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp',
......
......@@ -1642,6 +1642,13 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
INSERT_PROC_ADDRESS(egl, CreateDeviceANGLE);
INSERT_PROC_ADDRESS(egl, ReleaseDeviceANGLE);
// EGL_KHR_stream
INSERT_PROC_ADDRESS(egl, CreateStreamKHR);
INSERT_PROC_ADDRESS(egl, DestroyStreamKHR);
INSERT_PROC_ADDRESS(egl, StreamAttribKHR);
INSERT_PROC_ADDRESS(egl, QueryStreamKHR);
INSERT_PROC_ADDRESS(egl, QueryStreamu64KHR);
#undef INSERT_PROC_ADDRESS
return map;
};
......
......@@ -12,6 +12,7 @@
#include "libANGLE/Display.h"
#include "libANGLE/Device.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Stream.h"
#include "libANGLE/validationEGL.h"
#include "common/debug.h"
......@@ -551,4 +552,150 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device)
return EGL_TRUE;
}
// EGL_KHR_stream
EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLAttrib* attrib_list = 0x%0.8p)", dpy, attrib_list);
Display *display = static_cast<Display *>(dpy);
AttributeMap attributes(attrib_list);
Error error = ValidateCreateStreamKHR(display, attributes);
if (error.isError())
{
SetGlobalError(error);
return EGL_NO_STREAM_KHR;
}
Stream *stream;
error = display->createStream(attributes, &stream);
if (error.isError())
{
SetGlobalError(error);
return EGL_NO_STREAM_KHR;
}
return static_cast<EGLStreamKHR>(stream);
}
EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
Display *display = static_cast<Display *>(dpy);
Stream *streamObject = static_cast<Stream *>(stream);
Error error = ValidateDestroyStreamKHR(display, streamObject);
if (error.isError())
{
SetGlobalError(error);
return EGL_FALSE;
}
display->destroyStream(streamObject);
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLint value)
{
EVENT(
"(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
"EGLint value = 0x%X)",
dpy, stream, attribute, value);
Display *display = static_cast<Display *>(dpy);
Stream *streamObject = static_cast<Stream *>(stream);
Error error = ValidateStreamAttribKHR(display, streamObject, attribute, value);
if (error.isError())
{
SetGlobalError(error);
return EGL_FALSE;
}
switch (attribute)
{
case EGL_CONSUMER_LATENCY_USEC_KHR:
streamObject->setConsumerLatency(value);
break;
default:
UNREACHABLE();
}
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLint *value)
{
EVENT(
"(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
"EGLint value = 0x%0.8p)",
dpy, stream, attribute, value);
Display *display = static_cast<Display *>(dpy);
Stream *streamObject = static_cast<Stream *>(stream);
Error error = ValidateQueryStreamKHR(display, streamObject, attribute, value);
if (error.isError())
{
SetGlobalError(error);
return EGL_FALSE;
}
switch (attribute)
{
case EGL_STREAM_STATE_KHR:
*value = streamObject->getState();
break;
case EGL_CONSUMER_LATENCY_USEC_KHR:
*value = streamObject->getConsumerLatency();
break;
default:
UNREACHABLE();
}
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLuint64KHR *value)
{
EVENT(
"(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
"EGLuint64KHR value = 0x%0.8p)",
dpy, stream, attribute, value);
Display *display = static_cast<Display *>(dpy);
Stream *streamObject = static_cast<Stream *>(stream);
Error error = ValidateQueryStreamu64KHR(display, streamObject, attribute, value);
if (error.isError())
{
SetGlobalError(error);
return EGL_FALSE;
}
switch (attribute)
{
case EGL_PRODUCER_FRAME_KHR:
*value = streamObject->getProducerFrame();
break;
case EGL_CONSUMER_FRAME_KHR:
*value = streamObject->getConsumerFrame();
break;
default:
UNREACHABLE();
}
return EGL_TRUE;
}
}
......@@ -43,6 +43,22 @@ ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device);
// EGL_KHR_stream
ANGLE_EXPORT EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLint value);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLint *value);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
EGLuint64KHR *value);
}
#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
......@@ -85,6 +85,7 @@
'<(angle_path)/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLDeviceTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp',
'<(angle_path)/src/tests/egl_tests/EGLStreamTest.cpp',
# TODO(cwallez) for Linux, requires a portable implementation of threads
'<(angle_path)/src/tests/egl_tests/EGLThreadTest.cpp',
],
......
//
// Copyright 2016 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.
//
// EGLStreamTest:
// Tests pertaining to egl::Stream.
//
#include <gtest/gtest.h>
#include <vector>
#include "OSWindow.h"
#include "test_utils/ANGLETest.h"
using namespace angle;
namespace
{
class EGLStreamTest : public ANGLETest
{
protected:
EGLStreamTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
}
};
// Tests validation of the stream API
TEST_P(EGLStreamTest, StreamValidationTest)
{
EGLWindow *window = getEGLWindow();
const char *extensionsString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (strstr(extensionsString, "EGL_KHR_stream") == nullptr)
{
std::cout << "Stream extension not supported" << std::endl;
return;
}
EGLDisplay display = window->getDisplay();
const EGLint streamAttributesBad[] = {
EGL_STREAM_STATE_KHR,
0,
EGL_NONE,
EGL_PRODUCER_FRAME_KHR,
0,
EGL_NONE,
EGL_CONSUMER_FRAME_KHR,
0,
EGL_NONE,
EGL_CONSUMER_LATENCY_USEC_KHR,
-1,
EGL_NONE,
EGL_RED_SIZE,
EGL_DONT_CARE,
EGL_NONE,
};
// Validate create stream attributes
EGLStreamKHR stream = eglCreateStreamKHR(display, &streamAttributesBad[0]);
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
stream = eglCreateStreamKHR(display, &streamAttributesBad[3]);
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
stream = eglCreateStreamKHR(display, &streamAttributesBad[6]);
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
stream = eglCreateStreamKHR(display, &streamAttributesBad[9]);
ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
stream = eglCreateStreamKHR(display, &streamAttributesBad[12]);
ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
const EGLint streamAttributes[] = {
EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_NONE,
};
stream = eglCreateStreamKHR(EGL_NO_DISPLAY, streamAttributes);
ASSERT_EGL_ERROR(EGL_BAD_DISPLAY);
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
// Create an actual stream
stream = eglCreateStreamKHR(display, streamAttributes);
ASSERT_EGL_SUCCESS();
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
// Assert it is in the created state
EGLint state;
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
ASSERT_EGL_SUCCESS();
ASSERT_EQ(EGL_STREAM_STATE_CREATED_KHR, state);
// Test getting and setting the latency
EGLint latency = 10;
eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, latency);
ASSERT_EGL_SUCCESS();
eglQueryStreamKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, &latency);
ASSERT_EGL_SUCCESS();
ASSERT_EQ(10, latency);
eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, -1);
ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
ASSERT_EQ(10, latency);
// Test the 64-bit queries
EGLuint64KHR value;
eglQueryStreamu64KHR(display, stream, EGL_CONSUMER_FRAME_KHR, &value);
ASSERT_EGL_SUCCESS();
eglQueryStreamu64KHR(display, stream, EGL_PRODUCER_FRAME_KHR, &value);
ASSERT_EGL_SUCCESS();
// Destroy the stream
eglDestroyStreamKHR(display, stream);
ASSERT_EGL_SUCCESS();
}
ANGLE_INSTANTIATE_TEST(EGLStreamTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_OPENGL(),
ES3_OPENGL());
} // anonymous namespace
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