зеркало из https://github.com/AvaloniaUI/angle.git
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: Kenneth Russell <kbr@chromium.org>
This commit is contained in:
Родитель
2251102112
Коммит
b3eeb2a403
|
@ -21,7 +21,7 @@ Status
|
|||
Draft
|
||||
|
||||
Version
|
||||
Version 2, Apr 1, 2019
|
||||
Version 3, Aug 13, 2019
|
||||
|
||||
Number
|
||||
|
||||
|
@ -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_SHORT GL_R16UI
|
||||
GL_UNSIGNED_BYTE GL_RG
|
||||
GL_UNSIGNED_BYTE GL_RGB
|
||||
GL_UNSIGNED_BYTE GL_BGRA_EXT
|
||||
GL_HALF_FLOAT GL_RGBA
|
||||
---------------------------------------------------------------------------
|
||||
|
@ -110,9 +111,14 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
|
|||
|
||||
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
|
||||
|
||||
Version 1, 2017/12/06 - first draft.
|
||||
Version 2, 2019/04/01 - Allow MakeCurrent.
|
||||
Version 3, 2019/08/13 - Allow RGB internal formats
|
||||
|
|
|
@ -128,6 +128,18 @@ TextureTarget ImageIndex::getTarget() const
|
|||
return TextureTypeToTarget(mType, mLayerIndex);
|
||||
}
|
||||
|
||||
gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const
|
||||
{
|
||||
if (isEntireLevelCubeMap())
|
||||
{
|
||||
return gl::kCubeMapTextureTargetMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getTarget();
|
||||
}
|
||||
}
|
||||
|
||||
GLint ImageIndex::cubeMapFaceIndex() const
|
||||
{
|
||||
ASSERT(mType == TextureType::CubeMap);
|
||||
|
|
|
@ -40,6 +40,8 @@ class ImageIndex
|
|||
// map.
|
||||
TextureTarget getTarget() const;
|
||||
|
||||
TextureTarget getTargetOrFirstCubeFace() const;
|
||||
|
||||
bool isLayered() const;
|
||||
bool isEntireLevelCubeMap() const;
|
||||
|
||||
|
|
|
@ -926,6 +926,30 @@ angle::Result BlitGL::clearFramebuffer(FramebufferGL *source)
|
|||
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()
|
||||
{
|
||||
for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
|
||||
|
|
|
@ -126,6 +126,10 @@ class BlitGL : angle::NonCopyable
|
|||
|
||||
angle::Result clearFramebuffer(FramebufferGL *source);
|
||||
|
||||
angle::Result clearRenderableTextureAlphaToOne(GLuint texture,
|
||||
gl::TextureTarget target,
|
||||
size_t level);
|
||||
|
||||
angle::Result initializeResources();
|
||||
|
||||
private:
|
||||
|
|
|
@ -73,7 +73,7 @@ FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
|
|||
GLuint fbo = 0;
|
||||
funcs->genFramebuffers(1, &fbo);
|
||||
|
||||
return new FramebufferGL(data, fbo, false);
|
||||
return new FramebufferGL(data, fbo, false, false);
|
||||
}
|
||||
|
||||
TextureImpl *ContextGL::createTexture(const gl::TextureState &state)
|
||||
|
|
|
@ -218,12 +218,28 @@ bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabl
|
|||
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
|
||||
|
||||
FramebufferGL::FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault)
|
||||
FramebufferGL::FramebufferGL(const gl::FramebufferState &data,
|
||||
GLuint id,
|
||||
bool isDefault,
|
||||
bool emulatedAlpha)
|
||||
: FramebufferImpl(data),
|
||||
mFramebufferID(id),
|
||||
mIsDefault(isDefault),
|
||||
mHasEmulatedAlphaAttachment(emulatedAlpha),
|
||||
mAppliedEnabledDrawBuffers(1)
|
||||
{}
|
||||
|
||||
|
@ -1104,6 +1120,16 @@ angle::Result FramebufferGL::syncState(const gl::Context *context,
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
@ -1129,6 +1155,11 @@ bool FramebufferGL::isDefault() const
|
|||
return mIsDefault;
|
||||
}
|
||||
|
||||
bool FramebufferGL::hasEmulatedAlphaChannelTextureAttachment() const
|
||||
{
|
||||
return mHasEmulatedAlphaAttachment;
|
||||
}
|
||||
|
||||
void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
|
||||
{
|
||||
const FunctionsGL *functions = GetFunctionsGL(context);
|
||||
|
|
|
@ -23,7 +23,7 @@ class StateManagerGL;
|
|||
class FramebufferGL : public FramebufferImpl
|
||||
{
|
||||
public:
|
||||
FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault);
|
||||
FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault, bool emulatedAlpha);
|
||||
~FramebufferGL() override;
|
||||
|
||||
void destroy(const gl::Context *context) override;
|
||||
|
@ -88,6 +88,8 @@ class FramebufferGL : public FramebufferImpl
|
|||
GLuint getFramebufferID() const;
|
||||
bool isDefault() const;
|
||||
|
||||
bool hasEmulatedAlphaChannelTextureAttachment() const;
|
||||
|
||||
private:
|
||||
void syncClearState(const gl::Context *context, GLbitfield mask);
|
||||
void syncClearBufferState(const gl::Context *context, GLenum buffer, GLint drawBuffer);
|
||||
|
@ -130,6 +132,8 @@ class FramebufferGL : public FramebufferImpl
|
|||
GLuint mFramebufferID;
|
||||
bool mIsDefault;
|
||||
|
||||
bool mHasEmulatedAlphaAttachment;
|
||||
|
||||
gl::DrawBufferMask mAppliedEnabledDrawBuffers;
|
||||
};
|
||||
} // namespace rx
|
||||
|
|
|
@ -1489,15 +1489,6 @@ void StateManagerGL::syncState(const gl::Context *context,
|
|||
{
|
||||
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;
|
||||
if (!glAndLocalDirtyBits.any())
|
||||
{
|
||||
|
@ -1549,9 +1540,13 @@ void StateManagerGL::syncState(const gl::Context *context,
|
|||
}
|
||||
case gl::State::DIRTY_BIT_COLOR_MASK:
|
||||
{
|
||||
gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
|
||||
FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
|
||||
|
||||
const auto &blendState = state.getBlendState();
|
||||
setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
|
||||
blendState.colorMaskBlue, blendState.colorMaskAlpha);
|
||||
setColorMaskForFramebuffer(blendState.colorMaskRed, blendState.colorMaskGreen,
|
||||
blendState.colorMaskBlue, blendState.colorMaskAlpha,
|
||||
framebufferGL);
|
||||
break;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
|
||||
|
@ -1697,6 +1692,16 @@ void StateManagerGL::syncState(const gl::Context *context,
|
|||
{
|
||||
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;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
|
||||
|
@ -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)
|
||||
{
|
||||
if (mDitherEnabled != enabled)
|
||||
|
|
|
@ -136,6 +136,11 @@ class StateManagerGL final : angle::NonCopyable
|
|||
void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
|
||||
bool enabled,
|
||||
const FramebufferGL *framebuffer);
|
||||
void setColorMaskForFramebuffer(bool red,
|
||||
bool green,
|
||||
bool blue,
|
||||
bool alpha,
|
||||
const FramebufferGL *framebuffer);
|
||||
|
||||
void setDitherEnabled(bool enabled);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ SurfaceGL::~SurfaceGL() {}
|
|||
FramebufferImpl *SurfaceGL::createDefaultFramebuffer(const gl::Context *context,
|
||||
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)
|
||||
|
@ -46,4 +46,9 @@ angle::Result SurfaceGL::initializeContents(const gl::Context *context,
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
bool SurfaceGL::hasEmulatedAlphaChannel() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -26,6 +26,8 @@ class SurfaceGL : public SurfaceImpl
|
|||
|
||||
angle::Result initializeContents(const gl::Context *context,
|
||||
const gl::ImageIndex &imageIndex) override;
|
||||
|
||||
virtual bool hasEmulatedAlphaChannel() const;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "libANGLE/Context.h"
|
||||
#include "libANGLE/MemoryObject.h"
|
||||
#include "libANGLE/State.h"
|
||||
#include "libANGLE/Surface.h"
|
||||
#include "libANGLE/angletypes.h"
|
||||
#include "libANGLE/formatutils.h"
|
||||
#include "libANGLE/queryconversions.h"
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "libANGLE/renderer/gl/ImageGL.h"
|
||||
#include "libANGLE/renderer/gl/MemoryObjectGL.h"
|
||||
#include "libANGLE/renderer/gl/StateManagerGL.h"
|
||||
#include "libANGLE/renderer/gl/SurfaceGL.h"
|
||||
#include "libANGLE/renderer/gl/formatutilsgl.h"
|
||||
#include "libANGLE/renderer/gl/renderergl_utils.h"
|
||||
#include "platform/FeaturesGL.h"
|
||||
|
@ -72,7 +74,7 @@ LevelInfoGL GetLevelInfo(GLenum originalInternalFormat, GLenum destinationIntern
|
|||
GLenum destinationFormat = gl::GetUnsizedFormat(destinationInternalFormat);
|
||||
return LevelInfoGL(originalFormat, destinationInternalFormat,
|
||||
GetDepthStencilWorkaround(originalFormat),
|
||||
GetLUMAWorkaroundInfo(originalFormat, destinationFormat));
|
||||
GetLUMAWorkaroundInfo(originalFormat, destinationFormat), false);
|
||||
}
|
||||
|
||||
gl::Texture::DirtyBits GetLevelWorkaroundDirtyBits()
|
||||
|
@ -108,16 +110,18 @@ LUMAWorkaroundGL::LUMAWorkaroundGL(bool enabled_, GLenum workaroundFormat_)
|
|||
: enabled(enabled_), workaroundFormat(workaroundFormat_)
|
||||
{}
|
||||
|
||||
LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL()) {}
|
||||
LevelInfoGL::LevelInfoGL() : LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL(), false) {}
|
||||
|
||||
LevelInfoGL::LevelInfoGL(GLenum sourceFormat_,
|
||||
GLenum nativeInternalFormat_,
|
||||
bool depthStencilWorkaround_,
|
||||
const LUMAWorkaroundGL &lumaWorkaround_)
|
||||
const LUMAWorkaroundGL &lumaWorkaround_,
|
||||
bool emulatedAlphaChannel_)
|
||||
: sourceFormat(sourceFormat_),
|
||||
nativeInternalFormat(nativeInternalFormat_),
|
||||
depthStencilWorkaround(depthStencilWorkaround_),
|
||||
lumaWorkaround(lumaWorkaround_)
|
||||
lumaWorkaround(lumaWorkaround_),
|
||||
emulatedAlphaChannel(emulatedAlphaChannel_)
|
||||
{}
|
||||
|
||||
TextureGL::TextureGL(const gl::TextureState &state, GLuint id)
|
||||
|
@ -1177,7 +1181,11 @@ angle::Result TextureGL::bindTexImage(const gl::Context *context, egl::Surface *
|
|||
// Make sure this texture is bound
|
||||
stateManager->bindTexture(getType(), mTextureID);
|
||||
|
||||
setLevelInfo(context, getType(), 0, 1, LevelInfoGL());
|
||||
SurfaceGL *surfaceGL = GetImplAs<SurfaceGL>(surface);
|
||||
|
||||
setLevelInfo(context, getType(), 0, 1,
|
||||
LevelInfoGL(GL_NONE, GL_NONE, false, LUMAWorkaroundGL(),
|
||||
surfaceGL->hasEmulatedAlphaChannel()));
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
|
@ -1484,6 +1492,12 @@ GLenum TextureGL::getNativeInternalFormat(const gl::ImageIndex &index) const
|
|||
return getLevelInfo(index.getTarget(), index.getLevelIndex()).nativeInternalFormat;
|
||||
}
|
||||
|
||||
bool TextureGL::hasEmulatedAlphaChannel(const gl::ImageIndex &index) const
|
||||
{
|
||||
return getLevelInfo(index.getTargetOrFirstCubeFace(), index.getLevelIndex())
|
||||
.emulatedAlphaChannel;
|
||||
}
|
||||
|
||||
void TextureGL::syncTextureStateSwizzle(const gl::Context *context,
|
||||
const FunctionsGL *functions,
|
||||
GLenum name,
|
||||
|
@ -1492,107 +1506,110 @@ void TextureGL::syncTextureStateSwizzle(const gl::Context *context,
|
|||
{
|
||||
const LevelInfoGL &levelInfo = getBaseLevelInfo();
|
||||
GLenum resultSwizzle = value;
|
||||
if (levelInfo.lumaWorkaround.enabled || levelInfo.depthStencilWorkaround)
|
||||
if (levelInfo.lumaWorkaround.enabled)
|
||||
{
|
||||
if (levelInfo.lumaWorkaround.enabled)
|
||||
switch (value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case GL_RED:
|
||||
case GL_GREEN:
|
||||
case GL_BLUE:
|
||||
if (levelInfo.sourceFormat == GL_LUMINANCE ||
|
||||
levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
|
||||
{
|
||||
// Texture is backed by a RED or RG texture, point all color channels at the
|
||||
// red channel.
|
||||
ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
|
||||
levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
|
||||
resultSwizzle = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(levelInfo.sourceFormat == GL_ALPHA);
|
||||
// Color channels are not supposed to exist, make them always sample 0.
|
||||
resultSwizzle = GL_ZERO;
|
||||
}
|
||||
break;
|
||||
case GL_RED:
|
||||
case GL_GREEN:
|
||||
case GL_BLUE:
|
||||
if (levelInfo.sourceFormat == GL_LUMINANCE ||
|
||||
levelInfo.sourceFormat == GL_LUMINANCE_ALPHA)
|
||||
{
|
||||
// Texture is backed by a RED or RG texture, point all color channels at the
|
||||
// red channel.
|
||||
ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED ||
|
||||
levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
|
||||
resultSwizzle = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(levelInfo.sourceFormat == GL_ALPHA);
|
||||
// Color channels are not supposed to exist, make them always sample 0.
|
||||
resultSwizzle = GL_ZERO;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_ALPHA:
|
||||
if (levelInfo.sourceFormat == GL_LUMINANCE)
|
||||
{
|
||||
// Alpha channel is not supposed to exist, make it always sample 1.
|
||||
resultSwizzle = GL_ONE;
|
||||
}
|
||||
else if (levelInfo.sourceFormat == GL_ALPHA)
|
||||
{
|
||||
// Texture is backed by a RED texture, point the alpha channel at the red
|
||||
// channel.
|
||||
ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
|
||||
resultSwizzle = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(levelInfo.sourceFormat == GL_LUMINANCE_ALPHA);
|
||||
// Texture is backed by an RG texture, point the alpha channel at the green
|
||||
// channel.
|
||||
ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
|
||||
resultSwizzle = GL_GREEN;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_ZERO:
|
||||
case GL_ONE:
|
||||
// Don't modify the swizzle state when requesting ZERO or ONE.
|
||||
resultSwizzle = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(levelInfo.depthStencilWorkaround);
|
||||
switch (value)
|
||||
{
|
||||
case GL_RED:
|
||||
// Don't modify the swizzle state when requesting the red channel.
|
||||
resultSwizzle = value;
|
||||
break;
|
||||
|
||||
case GL_GREEN:
|
||||
case GL_BLUE:
|
||||
if (context->getClientMajorVersion() <= 2)
|
||||
{
|
||||
// In OES_depth_texture/ARB_depth_texture, depth
|
||||
// textures are treated as luminance.
|
||||
resultSwizzle = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// In GLES 3.0, depth textures are treated as RED
|
||||
// textures, so green and blue should be 0.
|
||||
resultSwizzle = GL_ZERO;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_ALPHA:
|
||||
// Depth textures should sample 1 from the alpha channel.
|
||||
case GL_ALPHA:
|
||||
if (levelInfo.sourceFormat == GL_LUMINANCE)
|
||||
{
|
||||
// Alpha channel is not supposed to exist, make it always sample 1.
|
||||
resultSwizzle = GL_ONE;
|
||||
break;
|
||||
}
|
||||
else if (levelInfo.sourceFormat == GL_ALPHA)
|
||||
{
|
||||
// Texture is backed by a RED texture, point the alpha channel at the red
|
||||
// channel.
|
||||
ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RED);
|
||||
resultSwizzle = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(levelInfo.sourceFormat == GL_LUMINANCE_ALPHA);
|
||||
// Texture is backed by an RG texture, point the alpha channel at the green
|
||||
// channel.
|
||||
ASSERT(levelInfo.lumaWorkaround.workaroundFormat == GL_RG);
|
||||
resultSwizzle = GL_GREEN;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_ZERO:
|
||||
case GL_ONE:
|
||||
// Don't modify the swizzle state when requesting ZERO or ONE.
|
||||
resultSwizzle = value;
|
||||
break;
|
||||
case GL_ZERO:
|
||||
case GL_ONE:
|
||||
// Don't modify the swizzle state when requesting ZERO or ONE.
|
||||
resultSwizzle = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (levelInfo.depthStencilWorkaround)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case GL_RED:
|
||||
// Don't modify the swizzle state when requesting the red channel.
|
||||
resultSwizzle = value;
|
||||
break;
|
||||
|
||||
case GL_GREEN:
|
||||
case GL_BLUE:
|
||||
if (context->getClientMajorVersion() <= 2)
|
||||
{
|
||||
// In OES_depth_texture/ARB_depth_texture, depth
|
||||
// textures are treated as luminance.
|
||||
resultSwizzle = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// In GLES 3.0, depth textures are treated as RED
|
||||
// textures, so green and blue should be 0.
|
||||
resultSwizzle = GL_ZERO;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_ALPHA:
|
||||
// Depth textures should sample 1 from the alpha channel.
|
||||
resultSwizzle = GL_ONE;
|
||||
break;
|
||||
|
||||
case GL_ZERO:
|
||||
case GL_ONE:
|
||||
// Don't modify the swizzle state when requesting ZERO or ONE.
|
||||
resultSwizzle = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (levelInfo.emulatedAlphaChannel)
|
||||
{
|
||||
if (value == GL_ALPHA)
|
||||
{
|
||||
resultSwizzle = GL_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,11 +47,16 @@ struct LevelInfoGL
|
|||
// Information about luminance alpha texture workarounds in the core profile.
|
||||
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(GLenum sourceFormat,
|
||||
GLenum nativeInternalFormat,
|
||||
bool depthStencilWorkaround,
|
||||
const LUMAWorkaroundGL &lumaWorkaround);
|
||||
const LUMAWorkaroundGL &lumaWorkaround,
|
||||
bool emulatedAlphaChannel);
|
||||
};
|
||||
|
||||
class TextureGL : public TextureImpl
|
||||
|
@ -199,6 +204,7 @@ class TextureGL : public TextureImpl
|
|||
void setSwizzle(const gl::Context *context, GLint swizzle[4]);
|
||||
|
||||
GLenum getNativeInternalFormat(const gl::ImageIndex &index) const;
|
||||
bool hasEmulatedAlphaChannel(const gl::ImageIndex &index) const;
|
||||
|
||||
private:
|
||||
void setImageHelper(const gl::Context *context,
|
||||
|
|
|
@ -64,13 +64,19 @@ class IOSurfaceSurfaceCGL : public SurfaceGL
|
|||
FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
|
||||
const gl::FramebufferState &state) override;
|
||||
|
||||
bool hasEmulatedAlphaChannel() const override;
|
||||
|
||||
private:
|
||||
angle::Result initializeAlphaChannel(const gl::Context *context, GLuint texture);
|
||||
|
||||
CGLContextObj mCGLContext;
|
||||
IOSurfaceRef mIOSurface;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
int mPlane;
|
||||
int mFormatIndex;
|
||||
|
||||
bool mAlphaInitialized;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
|
||||
#include "libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <IOSurface/IOSurface.h>
|
||||
#include <OpenGL/CGLIOSurface.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "libANGLE/AttributeMap.h"
|
||||
#include "libANGLE/renderer/gl/BlitGL.h"
|
||||
#include "libANGLE/renderer/gl/FramebufferGL.h"
|
||||
#include "libANGLE/renderer/gl/FunctionsGL.h"
|
||||
#include "libANGLE/renderer/gl/RendererGL.h"
|
||||
|
@ -44,6 +46,7 @@ static const IOSurfaceFormatInfo kIOSurfaceFormats[] = {
|
|||
{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_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_RGBA, GL_HALF_FLOAT, 8, GL_RGBA, GL_RGBA, GL_HALF_FLOAT },
|
||||
};
|
||||
|
@ -74,7 +77,8 @@ IOSurfaceSurfaceCGL::IOSurfaceSurfaceCGL(const egl::SurfaceState &state,
|
|||
mWidth(0),
|
||||
mHeight(0),
|
||||
mPlane(0),
|
||||
mFormatIndex(-1)
|
||||
mFormatIndex(-1),
|
||||
mAlphaInitialized(false)
|
||||
{
|
||||
// Keep reference to the IOSurface so it doesn't get deleted while the pbuffer exists.
|
||||
mIOSurface = reinterpret_cast<IOSurfaceRef>(buffer);
|
||||
|
@ -89,6 +93,8 @@ IOSurfaceSurfaceCGL::IOSurfaceSurfaceCGL(const egl::SurfaceState &state,
|
|||
EGLAttrib type = attribs.get(EGL_TEXTURE_TYPE_ANGLE);
|
||||
mFormatIndex = FindIOSurfaceFormatIndex(internalFormat, type);
|
||||
ASSERT(mFormatIndex >= 0);
|
||||
|
||||
mAlphaInitialized = !hasEmulatedAlphaChannel();
|
||||
}
|
||||
|
||||
IOSurfaceSurfaceCGL::~IOSurfaceSurfaceCGL()
|
||||
|
@ -148,13 +154,18 @@ egl::Error IOSurfaceSurfaceCGL::bindTexImage(const gl::Context *context,
|
|||
stateManager->bindTexture(gl::TextureType::Rectangle, textureID);
|
||||
|
||||
const auto &format = kIOSurfaceFormats[mFormatIndex];
|
||||
auto error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat,
|
||||
mWidth, mHeight, format.nativeInternalFormat,
|
||||
format.nativeType, mIOSurface, mPlane);
|
||||
CGLError error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat,
|
||||
mWidth, mHeight, format.nativeInternalFormat,
|
||||
format.nativeType, mIOSurface, mPlane);
|
||||
|
||||
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();
|
||||
|
@ -247,8 +258,9 @@ class IOSurfaceFramebuffer : public FramebufferGL
|
|||
IOSurfaceFramebuffer(const gl::FramebufferState &data,
|
||||
GLuint id,
|
||||
GLuint textureId,
|
||||
bool isDefault)
|
||||
: FramebufferGL(data, id, isDefault), mTextureId(textureId)
|
||||
bool isDefault,
|
||||
bool emulatedAlpha)
|
||||
: FramebufferGL(data, id, isDefault, emulatedAlpha), mTextureId(textureId)
|
||||
{}
|
||||
void destroy(const gl::Context *context) override
|
||||
{
|
||||
|
@ -273,8 +285,17 @@ FramebufferImpl *IOSurfaceSurfaceCGL::createDefaultFramebuffer(const gl::Context
|
|||
CGLError error = CGLTexImageIOSurface2D(mCGLContext, GL_TEXTURE_RECTANGLE, format.nativeFormat,
|
||||
mWidth, mHeight, format.nativeInternalFormat,
|
||||
format.nativeType, mIOSurface, mPlane);
|
||||
if (error != kCGLNoError)
|
||||
{
|
||||
ERR() << "CGLTexImageIOSurface2D failed: " << CGLErrorString(error);
|
||||
}
|
||||
ASSERT(error == kCGLNoError);
|
||||
|
||||
if (IsError(initializeAlphaChannel(context, texture)))
|
||||
{
|
||||
ERR() << "Failed to initialize IOSurface alpha channel.";
|
||||
}
|
||||
|
||||
GLuint framebuffer = 0;
|
||||
functions->genFramebuffers(1, &framebuffer);
|
||||
stateManager->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
|
@ -282,7 +303,27 @@ FramebufferImpl *IOSurfaceSurfaceCGL::createDefaultFramebuffer(const gl::Context
|
|||
functions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE,
|
||||
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
|
||||
|
|
|
@ -137,7 +137,7 @@ FramebufferImpl *PbufferSurfaceCGL::createDefaultFramebuffer(const gl::Context *
|
|||
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
mDSRenderbuffer);
|
||||
|
||||
return new FramebufferGL(state, framebuffer, true);
|
||||
return new FramebufferGL(state, framebuffer, true, false);
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -331,7 +331,7 @@ FramebufferImpl *WindowSurfaceCGL::createDefaultFramebuffer(const gl::Context *c
|
|||
functions->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
mDSRenderbuffer);
|
||||
|
||||
return new FramebufferGL(state, framebuffer, true);
|
||||
return new FramebufferGL(state, framebuffer, true, false);
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
|
|
@ -317,7 +317,7 @@ GLuint DisplayOzone::Buffer::createGLFB(const gl::Context *context)
|
|||
FramebufferGL *DisplayOzone::Buffer::framebufferGL(const gl::Context *context,
|
||||
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)
|
||||
|
|
|
@ -498,7 +498,7 @@ FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::Contex
|
|||
mDepthStencilRenderbufferID);
|
||||
}
|
||||
|
||||
return new FramebufferGL(data, framebufferID, true);
|
||||
return new FramebufferGL(data, framebufferID, true, false);
|
||||
}
|
||||
|
||||
HDC D3DTextureSurfaceWGL::getDC() const
|
||||
|
|
|
@ -296,7 +296,7 @@ FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer(
|
|||
}
|
||||
}
|
||||
|
||||
return new FramebufferGL(data, framebufferID, true);
|
||||
return new FramebufferGL(data, framebufferID, true, false);
|
||||
}
|
||||
|
||||
HDC DXGISwapChainWindowSurfaceWGL::getDC() const
|
||||
|
|
|
@ -331,6 +331,24 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
|
|||
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_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче