diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp b/gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp new file mode 100644 index 0000000000..ce2445c31e --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp @@ -0,0 +1,423 @@ +// +// Copyright 2002 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. +// + +// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class, +// GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#include "libANGLE/Renderbuffer.h" + +#include "common/utilities.h" +#include "libANGLE/Context.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Image.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/GLImplFactory.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace gl +{ +namespace +{ +angle::SubjectIndex kRenderbufferImplSubjectIndex = 0; + +InitState DetermineInitState(const Context *context) +{ + return (context && context->isRobustResourceInitEnabled()) ? InitState::MayNeedInit + : InitState::Initialized; +} +} // namespace + +// RenderbufferState implementation. +RenderbufferState::RenderbufferState() + : mWidth(0), + mHeight(0), + mFormat(GL_RGBA4), + mSamples(0), + mMultisamplingMode(MultisamplingMode::Regular), + mHasProtectedContent(false), + mInitState(InitState::Initialized) +{} + +RenderbufferState::~RenderbufferState() {} + +GLsizei RenderbufferState::getWidth() const +{ + return mWidth; +} + +GLsizei RenderbufferState::getHeight() const +{ + return mHeight; +} + +const Format &RenderbufferState::getFormat() const +{ + return mFormat; +} + +GLsizei RenderbufferState::getSamples() const +{ + return mSamples; +} + +MultisamplingMode RenderbufferState::getMultisamplingMode() const +{ + return mMultisamplingMode; +} + +InitState RenderbufferState::getInitState() const +{ + return mInitState; +} + +void RenderbufferState::update(GLsizei width, + GLsizei height, + const Format &format, + GLsizei samples, + MultisamplingMode multisamplingMode, + InitState initState) +{ + mWidth = width; + mHeight = height; + mFormat = format; + mSamples = samples; + mMultisamplingMode = multisamplingMode; + mInitState = initState; + mHasProtectedContent = false; +} + +void RenderbufferState::setProtectedContent(bool hasProtectedContent) +{ + mHasProtectedContent = hasProtectedContent; +} + +// Renderbuffer implementation. +Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id) + : RefCountObject(implFactory->generateSerial(), id), + mState(), + mImplementation(implFactory->createRenderbuffer(mState)), + mLabel(), + mImplObserverBinding(this, kRenderbufferImplSubjectIndex) +{ + mImplObserverBinding.bind(mImplementation.get()); +} + +void Renderbuffer::onDestroy(const Context *context) +{ + egl::RefCountObjectReleaser<egl::Image> releaseImage; + (void)orphanImages(context, &releaseImage); + + if (mImplementation) + { + mImplementation->onDestroy(context); + } +} + +Renderbuffer::~Renderbuffer() {} + +angle::Result Renderbuffer::setLabel(const Context *context, const std::string &label) +{ + mLabel = label; + + if (mImplementation) + { + return mImplementation->onLabelUpdate(context); + } + return angle::Result::Continue; +} + +const std::string &Renderbuffer::getLabel() const +{ + return mLabel; +} + +angle::Result Renderbuffer::setStorage(const Context *context, + GLenum internalformat, + GLsizei width, + GLsizei height) +{ + + egl::RefCountObjectReleaser<egl::Image> releaseImage; + ANGLE_TRY(orphanImages(context, &releaseImage)); + + ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height)); + + mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular, + DetermineInitState(context)); + onStateChange(angle::SubjectMessage::SubjectChanged); + + return angle::Result::Continue; +} + +angle::Result Renderbuffer::setStorageMultisample(const Context *context, + GLsizei samplesIn, + GLenum internalformat, + GLsizei width, + GLsizei height, + MultisamplingMode mode) +{ + egl::RefCountObjectReleaser<egl::Image> releaseImage; + ANGLE_TRY(orphanImages(context, &releaseImage)); + + // Potentially adjust "samplesIn" to a supported value + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + GLsizei samples = formatCaps.getNearestSamples(samplesIn); + + ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width, + height, mode)); + + mState.update(width, height, Format(internalformat), samples, mode, + DetermineInitState(context)); + onStateChange(angle::SubjectMessage::SubjectChanged); + + return angle::Result::Continue; +} + +angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image) +{ + egl::RefCountObjectReleaser<egl::Image> releaseImage; + ANGLE_TRY(orphanImages(context, &releaseImage)); + + ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image)); + + setTargetImage(context, image); + + mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()), + Format(image->getFormat()), 0, MultisamplingMode::Regular, + image->sourceInitState()); + mState.setProtectedContent(image->hasProtectedContent()); + + onStateChange(angle::SubjectMessage::SubjectChanged); + + return angle::Result::Continue; +} + +angle::Result Renderbuffer::copyRenderbufferSubData(Context *context, + const gl::Renderbuffer *srcBuffer, + GLint srcLevel, + GLint srcX, + GLint srcY, + GLint srcZ, + GLint dstLevel, + GLint dstX, + GLint dstY, + GLint dstZ, + GLsizei srcWidth, + GLsizei srcHeight, + GLsizei srcDepth) +{ + ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY, + srcZ, dstLevel, dstX, dstY, dstZ, srcWidth, + srcHeight, srcDepth)); + + return angle::Result::Continue; +} + +angle::Result Renderbuffer::copyTextureSubData(Context *context, + const gl::Texture *srcTexture, + GLint srcLevel, + GLint srcX, + GLint srcY, + GLint srcZ, + GLint dstLevel, + GLint dstX, + GLint dstY, + GLint dstZ, + GLsizei srcWidth, + GLsizei srcHeight, + GLsizei srcDepth) +{ + ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ, + dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, + srcDepth)); + + return angle::Result::Continue; +} + +rx::RenderbufferImpl *Renderbuffer::getImplementation() const +{ + ASSERT(mImplementation); + return mImplementation.get(); +} + +GLsizei Renderbuffer::getWidth() const +{ + return mState.mWidth; +} + +GLsizei Renderbuffer::getHeight() const +{ + return mState.mHeight; +} + +const Format &Renderbuffer::getFormat() const +{ + return mState.mFormat; +} + +GLsizei Renderbuffer::getSamples() const +{ + return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0; +} + +MultisamplingMode Renderbuffer::getMultisamplingMode() const +{ + return mState.mMultisamplingMode; +} + +GLuint Renderbuffer::getRedSize() const +{ + return mState.mFormat.info->redBits; +} + +GLuint Renderbuffer::getGreenSize() const +{ + return mState.mFormat.info->greenBits; +} + +GLuint Renderbuffer::getBlueSize() const +{ + return mState.mFormat.info->blueBits; +} + +GLuint Renderbuffer::getAlphaSize() const +{ + return mState.mFormat.info->alphaBits; +} + +GLuint Renderbuffer::getDepthSize() const +{ + return mState.mFormat.info->depthBits; +} + +GLuint Renderbuffer::getStencilSize() const +{ + return mState.mFormat.info->stencilBits; +} + +const RenderbufferState &Renderbuffer::getState() const +{ + return mState; +} + +GLint Renderbuffer::getMemorySize() const +{ + GLint implSize = mImplementation->getMemorySize(); + if (implSize > 0) + { + return implSize; + } + + // Assume allocated size is around width * height * samples * pixelBytes + angle::CheckedNumeric<GLint> size = 1; + size *= mState.mFormat.info->pixelBytes; + size *= mState.mWidth; + size *= mState.mHeight; + size *= std::max(mState.mSamples, 1); + return size.ValueOrDefault(std::numeric_limits<GLint>::max()); +} + +void Renderbuffer::onAttach(const Context *context, rx::Serial framebufferSerial) +{ + addRef(); +} + +void Renderbuffer::onDetach(const Context *context, rx::Serial framebufferSerial) +{ + release(context); +} + +GLuint Renderbuffer::getId() const +{ + return id().value; +} + +Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const +{ + return Extents(mState.mWidth, mState.mHeight, 1); +} + +Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/, + const ImageIndex & /*imageIndex*/) const +{ + return getFormat(); +} +GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const +{ + return getSamples(); +} + +bool Renderbuffer::isRenderable(const Context *context, + GLenum binding, + const ImageIndex &imageIndex) const +{ + if (isEGLImageTarget()) + { + return ImageSibling::isRenderable(context, binding, imageIndex); + } + return getFormat().info->renderbufferSupport(context->getClientVersion(), + context->getExtensions()); +} + +InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const +{ + if (isEGLImageTarget()) + { + return sourceEGLImageInitState(); + } + + return mState.mInitState; +} + +void Renderbuffer::setInitState(GLenum /*binding*/, + const gl::ImageIndex & /*imageIndex*/, + InitState initState) +{ + if (isEGLImageTarget()) + { + setSourceEGLImageInitState(initState); + } + else + { + mState.mInitState = initState; + } +} + +rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const +{ + return mImplementation.get(); +} + +GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const +{ + return mImplementation->getColorReadFormat(context); +} + +GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const +{ + return mImplementation->getColorReadType(context); +} + +angle::Result Renderbuffer::getRenderbufferImage(const Context *context, + const PixelPackState &packState, + Buffer *packBuffer, + GLenum format, + GLenum type, + void *pixels) const +{ + return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type, + pixels); +} + +void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) +{ + ASSERT(message == angle::SubjectMessage::SubjectChanged); + onStateChange(angle::SubjectMessage::ContentsChanged); +} +} // namespace gl |