blob: 65391a4478b46b73ac91c5f4623638e5ad673a5f [file] [log] [blame]
//
// Copyright 2020 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.
//
// PixmapSurfaceGLX.cpp: GLX implementation of egl::Surface for Pixmaps
#include "libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h"
#include "common/debug.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
#include "libANGLE/renderer/gl/glx/glx_utils.h"
#include <iostream>
namespace rx
{
namespace
{
int EGLTextureFormatToGLXTextureFormat(EGLint textureFormat)
{
switch (textureFormat)
{
case EGL_NO_TEXTURE:
return GLX_TEXTURE_FORMAT_NONE_EXT;
case EGL_TEXTURE_RGB:
return GLX_TEXTURE_FORMAT_RGB_EXT;
case EGL_TEXTURE_RGBA:
return GLX_TEXTURE_FORMAT_RGBA_EXT;
default:
UNREACHABLE();
return GLX_TEXTURE_FORMAT_NONE_EXT;
}
}
int EGLTextureTargetToGLXTextureTarget(EGLint textureTarget)
{
switch (textureTarget)
{
case EGL_NO_TEXTURE:
return 0;
case EGL_TEXTURE_2D:
return GLX_TEXTURE_2D_EXT;
default:
UNREACHABLE();
return 0;
}
}
int EGLBufferToGLXBuffer(EGLint buffer)
{
switch (buffer)
{
case EGL_BACK_BUFFER:
return GLX_BACK_EXT;
default:
UNREACHABLE();
return 0;
}
}
} // namespace
PixmapSurfaceGLX::PixmapSurfaceGLX(const egl::SurfaceState &state,
Pixmap pixmap,
Display *display,
const FunctionsGLX &glx,
glx::FBConfig fbConfig)
: SurfaceGLX(state),
mWidth(0),
mHeight(0),
mGLX(glx),
mFBConfig(fbConfig),
mXPixmap(pixmap),
mGLXPixmap(0),
mDisplay(display)
{}
PixmapSurfaceGLX::~PixmapSurfaceGLX()
{
if (mGLXPixmap)
{
mGLX.destroyPixmap(mGLXPixmap);
}
}
egl::Error PixmapSurfaceGLX::initialize(const egl::Display *display)
{
DisplayGLX *displayGLX = GetImplAs<DisplayGLX>(display);
{
Window rootWindow;
int x = 0;
int y = 0;
unsigned int borderWidth = 0;
unsigned int depth = 0;
int status = XGetGeometry(mDisplay, mXPixmap, &rootWindow, &x, &y, &mWidth, &mHeight,
&borderWidth, &depth);
if (!status)
{
return egl::EglBadSurface() << "XGetGeometry query failed on pixmap surface: "
<< x11::XErrorToString(mDisplay, status);
}
}
std::vector<int> pixmapAttribs;
if (mState.attributes.contains(EGL_TEXTURE_FORMAT))
{
pixmapAttribs.push_back(GLX_TEXTURE_FORMAT_EXT);
pixmapAttribs.push_back(
EGLTextureFormatToGLXTextureFormat(mState.attributes.getAsInt(EGL_TEXTURE_FORMAT)));
}
if (mState.attributes.contains(EGL_TEXTURE_TARGET))
{
pixmapAttribs.push_back(GLX_TEXTURE_TARGET_EXT);
pixmapAttribs.push_back(
EGLTextureTargetToGLXTextureTarget(mState.attributes.getAsInt(EGL_TEXTURE_TARGET)));
}
pixmapAttribs.push_back(None);
mGLXPixmap = mGLX.createPixmap(mFBConfig, mXPixmap, pixmapAttribs.data());
if (!mGLXPixmap)
{
return egl::EglBadAlloc() << "Failed to create a native GLX pixmap.";
}
XFlush(mDisplay);
displayGLX->syncXCommands(false);
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::makeCurrent(const gl::Context *context)
{
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::swap(const gl::Context *context)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::postSubBuffer(const gl::Context *context,
EGLint x,
EGLint y,
EGLint width,
EGLint height)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
{
UNREACHABLE();
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::bindTexImage(const gl::Context *context,
gl::Texture *texture,
EGLint buffer)
{
const int attribs[] = {None};
mGLX.bindTexImageEXT(mGLXPixmap, EGLBufferToGLXBuffer(buffer), attribs);
return egl::NoError();
}
egl::Error PixmapSurfaceGLX::releaseTexImage(const gl::Context *context, EGLint buffer)
{
mGLX.releaseTexImageEXT(mGLXPixmap, EGLBufferToGLXBuffer(buffer));
return egl::NoError();
}
void PixmapSurfaceGLX::setSwapInterval(EGLint interval) {}
EGLint PixmapSurfaceGLX::getWidth() const
{
return mWidth;
}
EGLint PixmapSurfaceGLX::getHeight() const
{
return mHeight;
}
EGLint PixmapSurfaceGLX::isPostSubBufferSupported() const
{
UNREACHABLE();
return EGL_FALSE;
}
EGLint PixmapSurfaceGLX::getSwapBehavior() const
{
return EGL_BUFFER_DESTROYED;
}
egl::Error PixmapSurfaceGLX::checkForResize()
{
// The size of pbuffers never change
return egl::NoError();
}
glx::Drawable PixmapSurfaceGLX::getDrawable() const
{
return mGLXPixmap;
}
} // namespace rx