327 lines
8.3 KiB
C++
327 lines
8.3 KiB
C++
//
|
|
// Copyright (c) 2002-2014 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.
|
|
//
|
|
|
|
// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
|
|
// such as the client area of a window, including any back buffers.
|
|
// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
|
|
|
|
#include "libANGLE/Surface.h"
|
|
|
|
#include <EGL/eglext.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include "libANGLE/Config.h"
|
|
#include "libANGLE/Framebuffer.h"
|
|
#include "libANGLE/Texture.h"
|
|
#include "libANGLE/formatutils.h"
|
|
#include "libANGLE/renderer/EGLImplFactory.h"
|
|
|
|
namespace egl
|
|
{
|
|
|
|
SurfaceState::SurfaceState() : defaultFramebuffer(nullptr)
|
|
{
|
|
}
|
|
|
|
Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
|
|
: FramebufferAttachmentObject(),
|
|
mImplementation(nullptr),
|
|
mCurrentCount(0),
|
|
mDestroyed(false),
|
|
mType(surfaceType),
|
|
mConfig(config),
|
|
mPostSubBufferRequested(false),
|
|
mFixedSize(false),
|
|
mFixedWidth(0),
|
|
mFixedHeight(0),
|
|
mTextureFormat(EGL_NO_TEXTURE),
|
|
mTextureTarget(EGL_NO_TEXTURE),
|
|
// FIXME: Determine actual pixel aspect ratio
|
|
mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
|
|
mRenderBuffer(EGL_BACK_BUFFER),
|
|
mSwapBehavior(EGL_NONE),
|
|
mOrientation(0),
|
|
mTexture(),
|
|
mBackFormat(config->renderTargetFormat),
|
|
mDSFormat(config->depthStencilFormat)
|
|
{
|
|
mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
|
|
mFlexibleSurfaceCompatibilityRequested =
|
|
(attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
|
|
|
|
mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
|
|
|
|
mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
|
|
if (mFixedSize)
|
|
{
|
|
mFixedWidth = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
|
|
mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
|
|
}
|
|
|
|
if (mType != EGL_WINDOW_BIT)
|
|
{
|
|
mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
|
|
mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
|
|
}
|
|
|
|
mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
|
|
}
|
|
|
|
Surface::~Surface()
|
|
{
|
|
if (mTexture.get())
|
|
{
|
|
if (mImplementation)
|
|
{
|
|
mImplementation->releaseTexImage(EGL_BACK_BUFFER);
|
|
}
|
|
mTexture->releaseTexImageFromSurface();
|
|
mTexture.set(nullptr);
|
|
}
|
|
|
|
SafeDelete(mState.defaultFramebuffer);
|
|
SafeDelete(mImplementation);
|
|
}
|
|
|
|
Error Surface::initialize()
|
|
{
|
|
ANGLE_TRY(mImplementation->initialize());
|
|
|
|
// Initialized here since impl is nullptr in the constructor.
|
|
// Must happen after implementation initialize for Android.
|
|
mSwapBehavior = mImplementation->getSwapBehavior();
|
|
|
|
// Must happen after implementation initialize for OSX.
|
|
mState.defaultFramebuffer = createDefaultFramebuffer();
|
|
ASSERT(mState.defaultFramebuffer != nullptr);
|
|
|
|
return Error(EGL_SUCCESS);
|
|
}
|
|
|
|
void Surface::setIsCurrent(bool isCurrent)
|
|
{
|
|
if (isCurrent)
|
|
{
|
|
mCurrentCount++;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(mCurrentCount > 0);
|
|
mCurrentCount--;
|
|
if (mCurrentCount == 0 && mDestroyed)
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Surface::onDestroy()
|
|
{
|
|
mDestroyed = true;
|
|
if (mCurrentCount == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
EGLint Surface::getType() const
|
|
{
|
|
return mType;
|
|
}
|
|
|
|
Error Surface::swap()
|
|
{
|
|
return mImplementation->swap();
|
|
}
|
|
|
|
Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
|
|
{
|
|
return mImplementation->postSubBuffer(x, y, width, height);
|
|
}
|
|
|
|
Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
|
|
{
|
|
return mImplementation->querySurfacePointerANGLE(attribute, value);
|
|
}
|
|
|
|
EGLint Surface::isPostSubBufferSupported() const
|
|
{
|
|
return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
|
|
}
|
|
|
|
void Surface::setSwapInterval(EGLint interval)
|
|
{
|
|
mImplementation->setSwapInterval(interval);
|
|
}
|
|
|
|
const Config *Surface::getConfig() const
|
|
{
|
|
return mConfig;
|
|
}
|
|
|
|
EGLint Surface::getPixelAspectRatio() const
|
|
{
|
|
return mPixelAspectRatio;
|
|
}
|
|
|
|
EGLenum Surface::getRenderBuffer() const
|
|
{
|
|
return mRenderBuffer;
|
|
}
|
|
|
|
EGLenum Surface::getSwapBehavior() const
|
|
{
|
|
return mSwapBehavior;
|
|
}
|
|
|
|
EGLenum Surface::getTextureFormat() const
|
|
{
|
|
return mTextureFormat;
|
|
}
|
|
|
|
EGLenum Surface::getTextureTarget() const
|
|
{
|
|
return mTextureTarget;
|
|
}
|
|
|
|
EGLint Surface::isFixedSize() const
|
|
{
|
|
return mFixedSize;
|
|
}
|
|
|
|
EGLint Surface::getWidth() const
|
|
{
|
|
return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
|
|
}
|
|
|
|
EGLint Surface::getHeight() const
|
|
{
|
|
return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
|
|
}
|
|
|
|
Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
|
|
{
|
|
ASSERT(!mTexture.get());
|
|
|
|
texture->bindTexImageFromSurface(this);
|
|
mTexture.set(texture);
|
|
return mImplementation->bindTexImage(texture, buffer);
|
|
}
|
|
|
|
Error Surface::releaseTexImage(EGLint buffer)
|
|
{
|
|
ASSERT(mTexture.get());
|
|
mTexture->releaseTexImageFromSurface();
|
|
mTexture.set(nullptr);
|
|
|
|
return mImplementation->releaseTexImage(buffer);
|
|
}
|
|
|
|
void Surface::releaseTexImageFromTexture()
|
|
{
|
|
ASSERT(mTexture.get());
|
|
mTexture.set(nullptr);
|
|
}
|
|
|
|
gl::Extents Surface::getAttachmentSize(const gl::FramebufferAttachment::Target & /*target*/) const
|
|
{
|
|
return gl::Extents(getWidth(), getHeight(), 1);
|
|
}
|
|
|
|
const gl::Format &Surface::getAttachmentFormat(
|
|
const gl::FramebufferAttachment::Target &target) const
|
|
{
|
|
return (target.binding() == GL_BACK ? mBackFormat : mDSFormat);
|
|
}
|
|
|
|
GLsizei Surface::getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const
|
|
{
|
|
return getConfig()->samples;
|
|
}
|
|
|
|
GLuint Surface::getId() const
|
|
{
|
|
UNREACHABLE();
|
|
return 0;
|
|
}
|
|
|
|
gl::Framebuffer *Surface::createDefaultFramebuffer()
|
|
{
|
|
gl::Framebuffer *framebuffer = new gl::Framebuffer(mImplementation);
|
|
|
|
GLenum drawBufferState = GL_BACK;
|
|
framebuffer->setDrawBuffers(1, &drawBufferState);
|
|
framebuffer->setReadBuffer(GL_BACK);
|
|
|
|
framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
|
|
this);
|
|
|
|
if (mConfig->depthSize > 0)
|
|
{
|
|
framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(),
|
|
this);
|
|
}
|
|
|
|
if (mConfig->stencilSize > 0)
|
|
{
|
|
framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
|
|
gl::ImageIndex::MakeInvalid(), this);
|
|
}
|
|
|
|
return framebuffer;
|
|
}
|
|
|
|
WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
|
|
const egl::Config *config,
|
|
EGLNativeWindowType window,
|
|
const AttributeMap &attribs)
|
|
: Surface(EGL_WINDOW_BIT, config, attribs)
|
|
{
|
|
mImplementation = implFactory->createWindowSurface(mState, config, window, attribs);
|
|
}
|
|
|
|
WindowSurface::~WindowSurface()
|
|
{
|
|
}
|
|
|
|
PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
|
|
const Config *config,
|
|
const AttributeMap &attribs)
|
|
: Surface(EGL_PBUFFER_BIT, config, attribs)
|
|
{
|
|
mImplementation = implFactory->createPbufferSurface(mState, config, attribs);
|
|
}
|
|
|
|
PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
|
|
const Config *config,
|
|
EGLClientBuffer shareHandle,
|
|
const AttributeMap &attribs)
|
|
: Surface(EGL_PBUFFER_BIT, config, attribs)
|
|
{
|
|
mImplementation =
|
|
implFactory->createPbufferFromClientBuffer(mState, config, shareHandle, attribs);
|
|
}
|
|
|
|
PbufferSurface::~PbufferSurface()
|
|
{
|
|
}
|
|
|
|
PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
|
|
const Config *config,
|
|
NativePixmapType nativePixmap,
|
|
const AttributeMap &attribs)
|
|
: Surface(EGL_PIXMAP_BIT, config, attribs)
|
|
{
|
|
mImplementation = implFactory->createPixmapSurface(mState, config, nativePixmap, attribs);
|
|
}
|
|
|
|
PixmapSurface::~PixmapSurface()
|
|
{
|
|
}
|
|
|
|
} // namespace egl
|