text: //
  // 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();
  
      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
  