Commit b3eeb2a4 by Geoff Lang Committed by Commit Bot

Emulate RGB textures using BGRX IOSurfaces.

When the user requests an IOSurface Pbuffer with an RGB format, emulate the missing alpha channel by clearing it to 1.0 and masking reads and writes in shaders. BUG=angleproject:3766 Change-Id: I58c992bf641d9ece0f923603f32640615150e4f3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1737437 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org>
parent 22511021
...@@ -21,7 +21,7 @@ Status ...@@ -21,7 +21,7 @@ Status
Draft Draft
Version Version
Version 2, Apr 1, 2019 Version 3, Aug 13, 2019
Number Number
...@@ -96,6 +96,7 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) ...@@ -96,6 +96,7 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
GL_UNSIGNED_BYTE GL_RED GL_UNSIGNED_BYTE GL_RED
GL_UNSIGNED_SHORT GL_R16UI GL_UNSIGNED_SHORT GL_R16UI
GL_UNSIGNED_BYTE GL_RG GL_UNSIGNED_BYTE GL_RG
GL_UNSIGNED_BYTE GL_RGB
GL_UNSIGNED_BYTE GL_BGRA_EXT GL_UNSIGNED_BYTE GL_BGRA_EXT
GL_HALF_FLOAT GL_RGBA GL_HALF_FLOAT GL_RGBA
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
...@@ -110,9 +111,14 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) ...@@ -110,9 +111,14 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Issues Issues
There are no issues, please move on. 1. Can RGB formats be supported?
RESOLVED: Support for RGB internal formats is added in version 3. Surfaces
with an RGB format will ensure that the alpha channel of the IOSurface is
reset to 1.0 when it is used.
Revision History Revision History
Version 1, 2017/12/06 - first draft. Version 1, 2017/12/06 - first draft.
Version 2, 2019/04/01 - Allow MakeCurrent. Version 2, 2019/04/01 - Allow MakeCurrent.
Version 3, 2019/08/13 - Allow RGB internal formats
...@@ -128,6 +128,18 @@ TextureTarget ImageIndex::getTarget() const ...@@ -128,6 +128,18 @@ TextureTarget ImageIndex::getTarget() const
return TextureTypeToTarget(mType, mLayerIndex); return TextureTypeToTarget(mType, mLayerIndex);
} }
gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const
{
if (isEntireLevelCubeMap())
{
return gl::kCubeMapTextureTargetMin;
}
else
{
return getTarget();
}
}
GLint ImageIndex::cubeMapFaceIndex() const GLint ImageIndex::cubeMapFaceIndex() const
{ {
ASSERT(mType == TextureType::CubeMap); ASSERT(mType == TextureType::CubeMap);
......
...@@ -40,6 +40,8 @@ class ImageIndex ...@@ -40,6 +40,8 @@ class ImageIndex
// map. // map.
TextureTarget getTarget() const; TextureTarget getTarget() const;
TextureTarget getTargetOrFirstCubeFace() const;
bool isLayered() const; bool isLayered() const;
bool isEntireLevelCubeMap() const; bool isEntireLevelCubeMap() const;
......
...@@ -926,6 +926,30 @@ angle::Result BlitGL::clearFramebuffer(FramebufferGL *source) ...@@ -926,6 +926,30 @@ angle::Result BlitGL::clearFramebuffer(FramebufferGL *source)
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result BlitGL::clearRenderableTextureAlphaToOne(GLuint texture,
gl::TextureTarget target,
size_t level)
{
// Clearing the alpha of 3D textures is not supported/needed yet.
ASSERT(nativegl::UseTexImage2D(TextureTargetToType(target)));
ANGLE_TRY(initializeResources());
mStateManager->setClearColor(gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f));
mStateManager->setColorMask(false, false, false, true);
mStateManager->setScissorTestEnabled(false);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ToGLenum(target),
texture, static_cast<GLint>(level));
mFunctions->clear(GL_COLOR_BUFFER_BIT);
// Unbind the texture from the the scratch framebuffer
mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
return angle::Result::Continue;
}
angle::Result BlitGL::initializeResources() angle::Result BlitGL::initializeResources()
{ {
for (size_t i = 0; i < ArraySize(mScratchTextures); i++) for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
......
...@@ -126,6 +126,10 @@ class BlitGL : angle::NonCopyable ...@@ -126,6 +126,10 @@ class BlitGL : angle::NonCopyable
angle::Result clearFramebuffer(FramebufferGL *source); angle::Result clearFramebuffer(FramebufferGL *source);
angle::Result clearRenderableTextureAlphaToOne(GLuint texture,
gl::TextureTarget target,
size_t level);
angle::Result initializeResources(); angle::Result initializeResources();
private: private:
......
...@@ -73,7 +73,7 @@ FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data) ...@@ -73,7 +73,7 @@ FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
GLuint fbo = 0; GLuint fbo = 0;
funcs->genFramebuffers(1, &fbo); funcs->genFramebuffers(1, &fbo);
return new FramebufferGL(data, fbo, false); return new FramebufferGL(data, fbo, false, false);
} }
TextureImpl *ContextGL::createTexture(const gl::TextureState &state) TextureImpl *ContextGL::createTexture(const gl::TextureState &state)
......
...@@ -218,12 +218,28 @@ bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabl ...@@ -218,12 +218,28 @@ bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabl
return false; return false;
} }
bool IsEmulatedAlphaChannelTextureAttachment(const FramebufferAttachment *attachment)
{
if (!attachment || attachment->type() != GL_TEXTURE)
{
return false;
}
const Texture *texture = attachment->getTexture();
const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
return textureGL->hasEmulatedAlphaChannel(attachment->getTextureImageIndex());
}
} // namespace } // namespace
FramebufferGL::FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault) FramebufferGL::FramebufferGL(const gl::FramebufferState &data,
GLuint id,
bool isDefault,
bool emulatedAlpha)
: FramebufferImpl(data), : FramebufferImpl(data),
mFramebufferID(id), mFramebufferID(id),
mIsDefault(isDefault), mIsDefault(isDefault),
mHasEmulatedAlphaAttachment(emulatedAlpha),
mAppliedEnabledDrawBuffers(1) mAppliedEnabledDrawBuffers(1)
{} {}
...@@ -1104,6 +1120,16 @@ angle::Result FramebufferGL::syncState(const gl::Context *context, ...@@ -1104,6 +1120,16 @@ angle::Result FramebufferGL::syncState(const gl::Context *context,
{ {
attachment = newAttachment; attachment = newAttachment;
} }
// Hiding an alpha channel is only supported when it's the first attachment
// currently. Assert that these emulated textures are not bound to a framebuffer
// using MRT.
if (index == 0)
{
mHasEmulatedAlphaAttachment =
IsEmulatedAlphaChannelTextureAttachment(attachment);
}
ASSERT(index == 0 || !IsEmulatedAlphaChannelTextureAttachment(attachment));
} }
break; break;
} }
...@@ -1129,6 +1155,11 @@ bool FramebufferGL::isDefault() const ...@@ -1129,6 +1155,11 @@ bool FramebufferGL::isDefault() const
return mIsDefault; return mIsDefault;
} }
bool FramebufferGL::hasEmulatedAlphaChannelTextureAttachment() const
{
return mHasEmulatedAlphaAttachment;
}
void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask) void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
{ {
const FunctionsGL *functions = GetFunctionsGL(context); const FunctionsGL *functions = GetFunctionsGL(context);
......
...@@ -23,7 +23,7 @@ class StateManagerGL; ...@@ -23,7 +23,7 @@ class StateManagerGL;
class FramebufferGL : public FramebufferImpl class FramebufferGL : public FramebufferImpl
{ {
public: public:
FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault); FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault, bool emulatedAlpha);
~FramebufferGL() override; ~FramebufferGL() override;
void destroy(const gl::Context *context) override; void destroy(const gl::Context *context) override;
...@@ -88,6 +88,8 @@ class FramebufferGL : public FramebufferImpl ...@@ -88,6 +88,8 @@ class FramebufferGL : public FramebufferImpl
GLuint getFramebufferID() const; GLuint getFramebufferID() const;
bool isDefault() const; bool isDefault() const;
bool hasEmulatedAlphaChannelTextureAttachment() const;
private: private:
void syncClearState(const gl::Context *context, GLbitfield mask); void syncClearState(const gl::Context *context, GLbitfield mask);
void syncClearBufferState(const gl::Context *context, GLenum buffer, GLint drawBuffer); void syncClearBufferState(const gl::Context *context, GLenum buffer, GLint drawBuffer);
...@@ -130,6 +132,8 @@ class FramebufferGL : public FramebufferImpl ...@@ -130,6 +132,8 @@ class FramebufferGL : public FramebufferImpl
GLuint mFramebufferID; GLuint mFramebufferID;
bool mIsDefault; bool mIsDefault;
bool mHasEmulatedAlphaAttachment;
gl::DrawBufferMask mAppliedEnabledDrawBuffers; gl::DrawBufferMask mAppliedEnabledDrawBuffers;
}; };
} // namespace rx } // namespace rx
......
...@@ -1489,15 +1489,6 @@ void StateManagerGL::syncState(const gl::Context *context, ...@@ -1489,15 +1489,6 @@ void StateManagerGL::syncState(const gl::Context *context,
{ {
const gl::State &state = context->getState(); const gl::State &state = context->getState();
// Changing the draw framebuffer binding sometimes requires resetting srgb blending.
if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING])
{
if (mFunctions->standard == STANDARD_GL_DESKTOP)
{
mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
}
}
const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask; const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
if (!glAndLocalDirtyBits.any()) if (!glAndLocalDirtyBits.any())
{ {
...@@ -1549,9 +1540,13 @@ void StateManagerGL::syncState(const gl::Context *context, ...@@ -1549,9 +1540,13 @@ void StateManagerGL::syncState(const gl::Context *context,
} }
case gl::State::DIRTY_BIT_COLOR_MASK: case gl::State::DIRTY_BIT_COLOR_MASK:
{ {
gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
const auto &blendState = state.getBlendState(); const auto &blendState = state.getBlendState();
setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, setColorMaskForFramebuffer(blendState.colorMaskRed, blendState.colorMaskGreen,
blendState.colorMaskBlue, blendState.colorMaskAlpha); blendState.colorMaskBlue, blendState.colorMaskAlpha,
framebufferGL);
break; break;
} }
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
...@@ -1697,6 +1692,16 @@ void StateManagerGL::syncState(const gl::Context *context, ...@@ -1697,6 +1692,16 @@ void StateManagerGL::syncState(const gl::Context *context,
{ {
updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState()); updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
} }
// Changing the draw framebuffer binding sometimes requires resetting srgb blending.
if (mFunctions->standard == STANDARD_GL_DESKTOP)
{
iter.setLaterBit(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
}
// If the framebuffer is emulating RGB on top of RGBA, the color mask has to be
// updated
iter.setLaterBit(gl::State::DIRTY_BIT_COLOR_MASK);
break; break;
} }
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
...@@ -1888,6 +1893,20 @@ void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context * ...@@ -1888,6 +1893,20 @@ void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *
} }
} }
void StateManagerGL::setColorMaskForFramebuffer(bool red,
bool green,
bool blue,
bool alpha,
const FramebufferGL *framebuffer)
{
bool modifiedAlphaMask = alpha;
if (framebuffer->hasEmulatedAlphaChannelTextureAttachment())
{
modifiedAlphaMask = false;
}
setColorMask(red, green, blue, modifiedAlphaMask);
}
void StateManagerGL::setDitherEnabled(bool enabled) void StateManagerGL::setDitherEnabled(bool enabled)
{ {
if (mDitherEnabled != enabled) if (mDitherEnabled != enabled)
......
...@@ -136,6 +136,11 @@ class StateManagerGL final : angle::NonCopyable ...@@ -136,6 +136,11 @@ class StateManagerGL final : angle::NonCopyable
void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context, void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
bool enabled, bool enabled,
const FramebufferGL *framebuffer); const FramebufferGL *framebuffer);
void setColorMaskForFramebuffer(bool red,
bool green,
bool blue,
bool alpha,
const FramebufferGL *framebuffer);
void setDitherEnabled(bool enabled); void setDitherEnabled(bool enabled);
......
...@@ -25,7 +25,7 @@ SurfaceGL::~SurfaceGL() {} ...@@ -25,7 +25,7 @@ SurfaceGL::~SurfaceGL() {}
FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::Context *context, FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &data) const gl::FramebufferState &data)
{ {
return new FramebufferGL(data, 0, true); return new FramebufferGL(data, 0, true, false);
} }
egl::Error SurfaceGL::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) egl::Error SurfaceGL::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
...@@ -46,4 +46,9 @@ angle::Result SurfaceGL::initializeContents(const gl::Context *context, ...@@ -46,4 +46,9 @@ angle::Result SurfaceGL::initializeContents(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
bool SurfaceGL::hasEmulatedAlphaChannel() const
{
return false;
}
} // namespace rx } // namespace rx
...@@ -26,6 +26,8 @@ class SurfaceGL : public SurfaceImpl ...@@ -26,6 +26,8 @@ class SurfaceGL : public SurfaceImpl
angle::Result initializeContents(const gl::Context *context, angle::Result initializeContents(const gl::Context *context,
const gl::ImageIndex &imageIndex) override; const gl::ImageIndex &imageIndex) override;
virtual bool hasEmulatedAlphaChannel() const;
}; };
} // namespace rx } // namespace rx
......
...@@ -47,11 +47,16 @@ struct LevelInfoGL ...@@ -47,11 +47,16 @@ struct LevelInfoGL
// Information about luminance alpha texture workarounds in the core profile. // Information about luminance alpha texture workarounds in the core profile.
LUMAWorkaroundGL lumaWorkaround; LUMAWorkaroundGL lumaWorkaround;
// If this texture level hides the fact that it has an alpha channel by setting the sampler
// parameters to always sample 1.0.
bool emulatedAlphaChannel;
LevelInfoGL(); LevelInfoGL();
LevelInfoGL(GLenum sourceFormat, LevelInfoGL(GLenum sourceFormat,
GLenum nativeInternalFormat, GLenum nativeInternalFormat,
bool depthStencilWorkaround, bool depthStencilWorkaround,
const LUMAWorkaroundGL &lumaWorkaround); const LUMAWorkaroundGL &lumaWorkaround,
bool emulatedAlphaChannel);
}; };
class TextureGL : public TextureImpl class TextureGL : public TextureImpl
...@@ -199,6 +204,7 @@ class TextureGL : public TextureImpl ...@@ -199,6 +204,7 @@ class TextureGL : public TextureImpl
void setSwizzle(const gl::Context *context, GLint swizzle[4]); void setSwizzle(const gl::Context *context, GLint swizzle[4]);
GLenum getNativeInternalFormat(const gl::ImageIndex &index) const; GLenum getNativeInternalFormat(const gl::ImageIndex &index) const;
bool hasEmulatedAlphaChannel(const gl::ImageIndex &index) const;
private: private:
void setImageHelper(const gl::Context *context, void setImageHelper(const gl::Context *context,
......
...@@ -64,13 +64,19 @@ class IOSurfaceSurfaceCGL : public SurfaceGL ...@@ -64,13 +64,19 @@ class IOSurfaceSurfaceCGL : public SurfaceGL
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context, FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state) override; const gl::FramebufferState &state) override;
bool hasEmulatedAlphaChannel() const override;
private: private:
angle::Result initializeAlphaChannel(const gl::Context *context, GLuint texture);
CGLContextObj mCGLContext; CGLContextObj mCGLContext;
IOSurfaceRef mIOSurface; IOSurfaceRef mIOSurface;
int mWidth; int mWidth;
int mHeight; int mHeight;
int mPlane; int mPlane;
int mFormatIndex; int mFormatIndex;
bool mAlphaInitialized;
}; };
} // namespace rx } // namespace rx
......
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
#include "libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h" #include "libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h"
#import <Cocoa/Cocoa.h>
#include <IOSurface/IOSurface.h> #include <IOSurface/IOSurface.h>
#include <OpenGL/CGLIOSurface.h> #include <OpenGL/CGLIOSurface.h>
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/AttributeMap.h" #include "libANGLE/AttributeMap.h"
#include "libANGLE/renderer/gl/BlitGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h" #include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/RendererGL.h" #include "libANGLE/renderer/gl/RendererGL.h"
...@@ -44,6 +46,7 @@ static const IOSurfaceFormatInfo kIOSurfaceFormats[] = { ...@@ -44,6 +46,7 @@ static const IOSurfaceFormatInfo kIOSurfaceFormats[] = {
{GL_RED, GL_UNSIGNED_BYTE, 1, GL_RED, GL_RED, GL_UNSIGNED_BYTE }, {GL_RED, GL_UNSIGNED_BYTE, 1, GL_RED, GL_RED, GL_UNSIGNED_BYTE },
{GL_R16UI, GL_UNSIGNED_SHORT, 2, GL_RED, GL_RED, GL_UNSIGNED_SHORT }, {GL_R16UI, GL_UNSIGNED_SHORT, 2, GL_RED, GL_RED, GL_UNSIGNED_SHORT },
{GL_RG, GL_UNSIGNED_BYTE, 2, GL_RG, GL_RG, GL_UNSIGNED_BYTE }, {GL_RG, GL_UNSIGNED_BYTE, 2, GL_RG, GL_RG, GL_UNSIGNED_BYTE },
{GL_RGB, GL_UNSIGNED_BYTE, 4, GL_BGRA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
{GL_BGRA_EXT, GL_UNSIGNED_BYTE, 4, GL_BGRA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, {GL_BGRA_EXT, GL_UNSIGNED_BYTE, 4, GL_BGRA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
{GL_RGBA, GL_HALF_FLOAT, 8, GL_RGBA, GL_RGBA, GL_HALF_FLOAT }, {GL_RGBA, GL_HALF_FLOAT, 8, GL_RGBA, GL_RGBA, GL_HALF_FLOAT },
}; };
...@@ -74,7 +77,8 @@ IOSurfaceSurfaceCGL::IOSurfaceSurfaceCGL(const egl::SurfaceState &state, ...@@ -74,7 +77,8 @@ IOSurfaceSurfaceCGL::IOSurfaceSurfaceCGL(const egl::SurfaceState &state,
mWidth(0), mWidth(0),
mHeight(0), mHeight(0),
mPlane(0), mPlane(0),
mFormatIndex(-1) mFormatIndex(-1),
mAlphaInitialized(false)
{ {
// Keep reference to the IOSurface so it doesn't get deleted while the pbuffer exists. // Keep reference to the IOSurface so it doesn't get deleted while the pbuffer exists.
mIOSurface = reinterpret_cast<IOSurfaceRef>(buffer); mIOSurface = reinterpret_cast<IOSurfaceRef>(buffer);
...@@ -89,6 +93,8 @@ IOSurfaceSurfaceCGL::IOSurfaceSurfaceCGL(const egl::SurfaceState &state, ...@@ -89,6 +93,8 @@ IOSurfaceSurfaceCGL::IOSurfaceSurfaceCGL(const egl::SurfaceState &state,
EGLAttrib type = attribs.get(EGL_TEXTURE_TYPE_ANGLE); EGLAttrib type = attribs.get(EGL_TEXTURE_TYPE_ANGLE);
mFormatIndex = FindIOSurfaceFormatIndex(internalFormat, type); mFormatIndex = FindIOSurfaceFormatIndex(internalFormat, type);
ASSERT(mFormatIndex >= 0); ASSERT(mFormatIndex >= 0);
mAlphaInitialized = !hasEmulatedAlphaChannel();
} }
IOSurfaceSurfaceCGL::~IOSurfaceSurfaceCGL() IOSurfaceSurfaceCGL::~IOSurfaceSurfaceCGL()
...@@ -148,13 +154,18 @@ egl::Error IOSurfaceSurfaceCGL::bindTexImage(const gl::Context *context, ...@@ -148,13 +154,18 @@ egl::Error IOSurfaceSurfaceCGL::bindTexImage(const gl::Context *context,
stateManager->bindTexture(gl::TextureType::Rectangle, textureID); stateManager->bindTexture(gl::TextureType::Rectangle, textureID);
const auto &format = kIOSurfaceFormats[mFormatIndex]; const auto &format = kIOSurfaceFormats[mFormatIndex];
auto error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat, CGLError error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat,
mWidth, mHeight, format.nativeInternalFormat, mWidth, mHeight, format.nativeInternalFormat,
format.nativeType, mIOSurface, mPlane); format.nativeType, mIOSurface, mPlane);
if (error != kCGLNoError) if (error != kCGLNoError)
{ {
return egl::EglContextLost(); return egl::EglContextLost() << "CGLTexImageIOSurface2D failed: " << CGLErrorString(error);
}
if (IsError(initializeAlphaChannel(context, textureID)))
{
return egl::EglContextLost() << "Failed to initialize IOSurface alpha channel.";
} }
return egl::NoError(); return egl::NoError();
...@@ -247,8 +258,9 @@ class IOSurfaceFramebuffer : public FramebufferGL ...@@ -247,8 +258,9 @@ class IOSurfaceFramebuffer : public FramebufferGL
IOSurfaceFramebuffer(const gl::FramebufferState &data, IOSurfaceFramebuffer(const gl::FramebufferState &data,
GLuint id, GLuint id,
GLuint textureId, GLuint textureId,
bool isDefault) bool isDefault,
: FramebufferGL(data, id, isDefault), mTextureId(textureId) bool emulatedAlpha)
: FramebufferGL(data, id, isDefault, emulatedAlpha), mTextureId(textureId)
{} {}
void destroy(const gl::Context *context) override void destroy(const gl::Context *context) override
{ {
...@@ -273,8 +285,17 @@ FramebufferImpl *IOSurfaceSurfaceCGL::createDefaultFramebuffer(const gl::Context ...@@ -273,8 +285,17 @@ FramebufferImpl *IOSurfaceSurfaceCGL::createDefaultFramebuffer(const gl::Context
CGLError error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat, CGLError error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat,
mWidth, mHeight, format.nativeInternalFormat, mWidth, mHeight, format.nativeInternalFormat,
format.nativeType, mIOSurface, mPlane); format.nativeType, mIOSurface, mPlane);
if (error != kCGLNoError)
{
ERR() << "CGLTexImageIOSurface2D failed: " << CGLErrorString(error);
}
ASSERT(error == kCGLNoError); ASSERT(error == kCGLNoError);
if (IsError(initializeAlphaChannel(context, texture)))
{
ERR() << "Failed to initialize IOSurface alpha channel.";
}
GLuint framebuffer = 0; GLuint framebuffer = 0;
functions->genFramebuffers(1, &framebuffer); functions->genFramebuffers(1, &framebuffer);
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
...@@ -282,7 +303,27 @@ FramebufferImpl *IOSurfaceSurfaceCGL::createDefaultFramebuffer(const gl::Context ...@@ -282,7 +303,27 @@ FramebufferImpl *IOSurfaceSurfaceCGL::createDefaultFramebuffer(const gl::Context
functions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, functions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE,
texture, 0); texture, 0);
return new IOSurfaceFramebuffer(state, framebuffer, texture, true); return new IOSurfaceFramebuffer(state, framebuffer, texture, true, hasEmulatedAlphaChannel());
}
angle::Result IOSurfaceSurfaceCGL::initializeAlphaChannel(const gl::Context *context,
GLuint texture)
{
if (mAlphaInitialized)
{
return angle::Result::Continue;
}
BlitGL *blitter = GetBlitGL(context);
ANGLE_TRY(blitter->clearRenderableTextureAlphaToOne(texture, gl::TextureTarget::Rectangle, 0));
mAlphaInitialized = true;
return angle::Result::Continue;
}
bool IOSurfaceSurfaceCGL::hasEmulatedAlphaChannel() const
{
const auto &format = kIOSurfaceFormats[mFormatIndex];
return format.internalFormat == GL_RGB;
} }
} // namespace rx } // namespace rx
...@@ -137,7 +137,7 @@ FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::Context * ...@@ -137,7 +137,7 @@ FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::Context *
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSRenderbuffer); mDSRenderbuffer);
return new FramebufferGL(state, framebuffer, true); return new FramebufferGL(state, framebuffer, true, false);
} }
} // namespace rx } // namespace rx
...@@ -331,7 +331,7 @@ FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::Context *c ...@@ -331,7 +331,7 @@ FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::Context *c
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
mDSRenderbuffer); mDSRenderbuffer);
return new FramebufferGL(state, framebuffer, true); return new FramebufferGL(state, framebuffer, true, false);
} }
} // namespace rx } // namespace rx
...@@ -317,7 +317,7 @@ GLuint DisplayOzone::Buffer::createGLFB(const gl::Context *context) ...@@ -317,7 +317,7 @@ GLuint DisplayOzone::Buffer::createGLFB(const gl::Context *context)
FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::Context *context, FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::Context *context,
const gl::FramebufferState &state) const gl::FramebufferState &state)
{ {
return new FramebufferGL(state, createGLFB(context), true); return new FramebufferGL(state, createGLFB(context), true, false);
} }
void DisplayOzone::Buffer::present(const gl::Context *context) void DisplayOzone::Buffer::present(const gl::Context *context)
......
...@@ -498,7 +498,7 @@ FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::Contex ...@@ -498,7 +498,7 @@ FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::Contex
mDepthStencilRenderbufferID); mDepthStencilRenderbufferID);
} }
return new FramebufferGL(data, framebufferID, true); return new FramebufferGL(data, framebufferID, true, false);
} }
HDC D3DTextureSurfaceWGL::getDC() const HDC D3DTextureSurfaceWGL::getDC() const
......
...@@ -296,7 +296,7 @@ FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer( ...@@ -296,7 +296,7 @@ FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer(
} }
} }
return new FramebufferGL(data, framebufferID, true); return new FramebufferGL(data, framebufferID, true, false);
} }
HDC DXGISwapChainWindowSurfaceWGL::getDC() const HDC DXGISwapChainWindowSurfaceWGL::getDC() const
......
...@@ -331,6 +331,24 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface) ...@@ -331,6 +331,24 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
doSampleTest(ioSurface, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &color, sizeof(color), R | G | B | A); doSampleTest(ioSurface, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &color, sizeof(color), R | G | B | A);
} }
// Test using BGRX8888 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToBGRX8888IOSurface)
{
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
GLColor color(3, 2, 1, 255);
doClearTest(ioSurface, GL_RGB, GL_UNSIGNED_BYTE, &color, sizeof(color));
}
// Test reading from BGRX8888 IOSurfaces
TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurface)
{
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
GLColor color(3, 2, 1, 4);
doSampleTest(ioSurface, GL_RGB, GL_UNSIGNED_BYTE, &color, sizeof(color), R | G | B);
}
// Test using RG88 IOSurfaces for rendering // Test using RG88 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface) TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
{ {
......
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