diff options
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm')
-rwxr-xr-x | gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm new file mode 100755 index 000000000..f87134c82 --- /dev/null +++ b/gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm @@ -0,0 +1,275 @@ +// +// Copyright (c) 2015 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. +// + +// DisplayCGL.mm: CGL implementation of egl::Display + +#include "libANGLE/renderer/gl/cgl/DisplayCGL.h" + +#import <Cocoa/Cocoa.h> +#include <dlfcn.h> +#include <EGL/eglext.h> + +#include "common/debug.h" +#include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h" +#include "libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h" + +namespace +{ + +const char *kDefaultOpenGLDylibName = + "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; +const char *kFallbackOpenGLDylibName = "GL"; + +} + +namespace rx +{ + +class FunctionsGLCGL : public FunctionsGL +{ + public: + FunctionsGLCGL(void *dylibHandle) : mDylibHandle(dylibHandle) {} + + ~FunctionsGLCGL() override { dlclose(mDylibHandle); } + + private: + void *loadProcAddress(const std::string &function) override + { + return dlsym(mDylibHandle, function.c_str()); + } + + void *mDylibHandle; +}; + +DisplayCGL::DisplayCGL() : DisplayGL(), mEGLDisplay(nullptr), mFunctions(nullptr), mContext(nullptr) +{ +} + +DisplayCGL::~DisplayCGL() +{ +} + +egl::Error DisplayCGL::initialize(egl::Display *display) +{ + mEGLDisplay = display; + + CGLPixelFormatObj pixelFormat; + { + // TODO(cwallez) investigate which pixel format we want + CGLPixelFormatAttribute attribs[] = { + kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_3_2_Core), + static_cast<CGLPixelFormatAttribute>(0)}; + GLint nVirtualScreens = 0; + CGLChoosePixelFormat(attribs, &pixelFormat, &nVirtualScreens); + + if (pixelFormat == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create the context's pixel format."); + } + } + + CGLCreateContext(pixelFormat, nullptr, &mContext); + if (mContext == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not create the CGL context."); + } + CGLSetCurrentContext(mContext); + + // There is no equivalent getProcAddress in CGL so we open the dylib directly + void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW); + if (!handle) + { + handle = dlopen(kFallbackOpenGLDylibName, RTLD_NOW); + } + if (!handle) + { + return egl::Error(EGL_NOT_INITIALIZED, "Could not open the OpenGL Framework."); + } + + mFunctions = new FunctionsGLCGL(handle); + mFunctions->initialize(); + + return DisplayGL::initialize(display); +} + +void DisplayCGL::terminate() +{ + DisplayGL::terminate(); + + if (mContext != nullptr) + { + CGLSetCurrentContext(nullptr); + CGLReleaseContext(mContext); + mContext = nullptr; + } + + SafeDelete(mFunctions); +} + +SurfaceImpl *DisplayCGL::createWindowSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) +{ + return new WindowSurfaceCGL(state, this->getRenderer(), window, mFunctions, mContext); +} + +SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + const egl::AttributeMap &attribs) +{ + EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0)); + EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0)); + return new PbufferSurfaceCGL(state, this->getRenderer(), width, height, mFunctions); +} + +SurfaceImpl *DisplayCGL::createPbufferFromClientBuffer(const egl::SurfaceState &state, + const egl::Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +SurfaceImpl *DisplayCGL::createPixmapSurface(const egl::SurfaceState &state, + const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) +{ + UNIMPLEMENTED(); + return nullptr; +} + +egl::Error DisplayCGL::getDevice(DeviceImpl **device) +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::ConfigSet DisplayCGL::generateConfigs() +{ + // TODO(cwallez): generate more config permutations + egl::ConfigSet configs; + + const gl::Version &maxVersion = getMaxSupportedESVersion(); + ASSERT(maxVersion >= gl::Version(2, 0)); + bool supportsES3 = maxVersion >= gl::Version(3, 0); + + egl::Config config; + + // Native stuff + config.nativeVisualID = 0; + config.nativeVisualType = 0; + config.nativeRenderable = EGL_TRUE; + + // Buffer sizes + config.redSize = 8; + config.greenSize = 8; + config.blueSize = 8; + config.alphaSize = 8; + config.depthSize = 24; + config.stencilSize = 8; + + config.colorBufferType = EGL_RGB_BUFFER; + config.luminanceSize = 0; + config.alphaMaskSize = 0; + + config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize; + + config.transparentType = EGL_NONE; + + // Pbuffer + config.maxPBufferWidth = 4096; + config.maxPBufferHeight = 4096; + config.maxPBufferPixels = 4096 * 4096; + + // Caveat + config.configCaveat = EGL_NONE; + + // Misc + config.sampleBuffers = 0; + config.samples = 0; + config.level = 0; + config.bindToTextureRGB = EGL_FALSE; + config.bindToTextureRGBA = EGL_FALSE; + + config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + + config.minSwapInterval = 1; + config.maxSwapInterval = 1; + + config.renderTargetFormat = GL_RGBA8; + config.depthStencilFormat = GL_DEPTH24_STENCIL8; + + config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.renderableType = config.conformant; + + config.matchNativePixmap = EGL_NONE; + + configs.add(config); + return configs; +} + +bool DisplayCGL::testDeviceLost() +{ + // TODO(cwallez) investigate implementing this + return false; +} + +egl::Error DisplayCGL::restoreLostDevice() +{ + UNIMPLEMENTED(); + return egl::Error(EGL_BAD_DISPLAY); +} + +bool DisplayCGL::isValidNativeWindow(EGLNativeWindowType window) const +{ + // TODO(cwallez) investigate implementing this + return true; +} + +std::string DisplayCGL::getVendorString() const +{ + // TODO(cwallez) find a useful vendor string + return ""; +} + +const FunctionsGL *DisplayCGL::getFunctionsGL() const +{ + return mFunctions; +} + +void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ +} + +void DisplayCGL::generateCaps(egl::Caps *outCaps) const +{ + outCaps->textureNPOT = true; +} + +egl::Error DisplayCGL::waitClient() const +{ + // TODO(cwallez) UNIMPLEMENTED() + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayCGL::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + // TODO(cwallez) UNIMPLEMENTED() + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayCGL::getDriverVersion(std::string *version) const +{ + *version = ""; + return egl::Error(EGL_SUCCESS); +} +} |