<commit_before>/*
 * Copyright (C) 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "gapir/cc/gles_gfx_api.h"
#include "gapir/cc/gles_renderer.h"

#include "core/cc/gl/formats.h"
#include "core/cc/gl/versions.h"
#include "core/cc/log.h"

#include <cstring>
#include <X11/Xresource.h>

namespace gapir {
namespace {

typedef XID GLXPbuffer;
typedef XID GLXDrawable;
typedef /*struct __GLXcontextRec*/ void *GLXContext;
typedef /*struct __GLXFBConfigRec*/ void *GLXFBConfig;

enum {
    // Used by glXChooseFBConfig.
    GLX_RED_SIZE      = 8,
    GLX_GREEN_SIZE    = 9,
    GLX_BLUE_SIZE     = 10,
    GLX_ALPHA_SIZE    = 11,
    GLX_DEPTH_SIZE    = 12,
    GLX_STENCIL_SIZE  = 13,
    GLX_DRAWABLE_TYPE = 0x8010,
    GLX_RENDER_TYPE   = 0x8011,
    GLX_RGBA_BIT      = 0x00000001,
    GLX_PBUFFER_BIT   = 0x00000004,

    // Used by glXCreateNewContext.
    GLX_RGBA_TYPE = 0x8014,

    // Used by glXCreatePbuffer.
    GLX_PBUFFER_HEIGHT = 0x8040,
    GLX_PBUFFER_WIDTH  = 0x8041,

    // Attribute name for glXCreateContextAttribsARB.
    GLX_CONTEXT_MAJOR_VERSION_ARB             = 0x2091,
    GLX_CONTEXT_MINOR_VERSION_ARB             = 0x2092,
    GLX_CONTEXT_FLAGS_ARB                     = 0x2094,
    GLX_CONTEXT_PROFILE_MASK_ARB              = 0x9126,

    // Attribute value for glXCreateContextAttribsARB.
    GLX_CONTEXT_DEBUG_BIT_ARB                 = 0x0001,
    GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB    = 0x0002,
    GLX_CONTEXT_CORE_PROFILE_BIT_ARB          = 0x0001,
    GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x0002,
};

extern "C" {

GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list, int *nelements);
GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type,
                               GLXContext share_list, Bool direct);
GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list);
void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf);
Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
Bool glXQueryVersion(Display *dpy, int *maj, int *min);
void glXDestroyContext(Display *dpy, GLXContext ctx);
void* glXGetProcAddress(const char* procName);
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *dpy, GLXFBConfig config, GLXContext share_context,
                                                     Bool direct, const int *attrib_list);

} // extern "C"

class GlesRendererImpl : public GlesRenderer {
public:
    GlesRendererImpl(GlesRendererImpl* shared_context);
    virtual ~GlesRendererImpl() override;

    virtual Api* api() override;
    virtual void setBackbuffer(Backbuffer backbuffer) override;
    virtual void bind() override;
    virtual void unbind() override;
    virtual const char* name() override;
    virtual const char* extensions() override;
    virtual const char* vendor() override;
    virtual const char* version() override;

private:
    void reset();
    void createPbuffer(int width, int height);

    Backbuffer mBackbuffer;
    bool mBound;
    bool mNeedsResolve;
    Gles mApi;
    std::string mExtensions;
    bool mQueriedExtensions;

    Display *mDisplay;
    GLXContext mContext;
    GLXContext mSharedContext;
    GLXPbuffer mPbuffer;
    GLXFBConfig mFBConfig;
};

GlesRendererImpl::GlesRendererImpl(GlesRendererImpl* shared_context)
        : mBound(false)
        , mNeedsResolve(false)
        , mDisplay(nullptr)
        , mContext(nullptr)
        , mSharedContext(shared_context != nullptr ? shared_context->mContext : 0)
        , mPbuffer(0) {

    mDisplay = XOpenDisplay(nullptr);
    if (mDisplay == nullptr) {
        GAPID_FATAL("Unable to to open X display");
    }

    int major;
    int minor;
    if (!glXQueryVersion(mDisplay, &major, &minor) || (major == 1 && minor < 3)) {
        GAPID_FATAL("GLX 1.3+ unsupported by X server (was %d.%d)", major, minor);
    }

    // Initialize with a default target.
    setBackbuffer(Backbuffer(
          8, 8,
          core::gl::GL_RGBA8,
          core::gl::GL_DEPTH24_STENCIL8,
          core::gl::GL_DEPTH24_STENCIL8));
}

GlesRendererImpl::~GlesRendererImpl() {
    reset();

    if (mDisplay != nullptr) {
        XCloseDisplay(mDisplay);
    }
}

Api* GlesRendererImpl::api() {
  return &mApi;
}

void GlesRendererImpl::reset() {
    unbind();

    if (mContext != nullptr) {
        glXDestroyContext(mDisplay, mContext);
        GAPID_DEBUG("Destroyed context %p", mContext);
        mContext = nullptr;
    }

    if (mPbuffer != 0) {
        glXDestroyPbuffer(mDisplay, mPbuffer);<commit_msg>Shared contexts also need to share X-display<commit_after>/*
 * Copyright (C) 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "gapir/cc/gles_gfx_api.h"
#include "gapir/cc/gles_renderer.h"

#include "core/cc/gl/formats.h"
#include "core/cc/gl/versions.h"
#include "core/cc/log.h"

#include <cstring>
#include <X11/Xresource.h>

namespace gapir {
namespace {

typedef XID GLXPbuffer;
typedef XID GLXDrawable;
typedef /*struct __GLXcontextRec*/ void *GLXContext;
typedef /*struct __GLXFBConfigRec*/ void *GLXFBConfig;

enum {
    // Used by glXChooseFBConfig.
    GLX_RED_SIZE      = 8,
    GLX_GREEN_SIZE    = 9,
    GLX_BLUE_SIZE     = 10,
    GLX_ALPHA_SIZE    = 11,
    GLX_DEPTH_SIZE    = 12,
    GLX_STENCIL_SIZE  = 13,
    GLX_DRAWABLE_TYPE = 0x8010,
    GLX_RENDER_TYPE   = 0x8011,
    GLX_RGBA_BIT      = 0x00000001,
    GLX_PBUFFER_BIT   = 0x00000004,

    // Used by glXCreateNewContext.
    GLX_RGBA_TYPE = 0x8014,

    // Used by glXCreatePbuffer.
    GLX_PBUFFER_HEIGHT = 0x8040,
    GLX_PBUFFER_WIDTH  = 0x8041,

    // Attribute name for glXCreateContextAttribsARB.
    GLX_CONTEXT_MAJOR_VERSION_ARB             = 0x2091,
    GLX_CONTEXT_MINOR_VERSION_ARB             = 0x2092,
    GLX_CONTEXT_FLAGS_ARB                     = 0x2094,
    GLX_CONTEXT_PROFILE_MASK_ARB              = 0x9126,

    // Attribute value for glXCreateContextAttribsARB.
    GLX_CONTEXT_DEBUG_BIT_ARB                 = 0x0001,
    GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB    = 0x0002,
    GLX_CONTEXT_CORE_PROFILE_BIT_ARB          = 0x0001,
    GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x0002,
};

extern "C" {

GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list, int *nelements);
GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type,
                               GLXContext share_list, Bool direct);
GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list);
void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf);
Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
Bool glXQueryVersion(Display *dpy, int *maj, int *min);
void glXDestroyContext(Display *dpy, GLXContext ctx);
void* glXGetProcAddress(const char* procName);
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *dpy, GLXFBConfig config, GLXContext share_context,
                                                     Bool direct, const int *attrib_list);

} // extern "C"

class GlesRendererImpl : public GlesRenderer {
public:
    GlesRendererImpl(GlesRendererImpl* shared_context);
    virtual ~GlesRendererImpl() override;

    virtual Api* api() override;
    virtual void setBackbuffer(Backbuffer backbuffer) override;
    virtual void bind() override;
    virtual void unbind() override;
    virtual const char* name() override;
    virtual const char* extensions() override;
    virtual const char* vendor() override;
    virtual const char* version() override;

private:
    void reset();
    void createPbuffer(int width, int height);

    Backbuffer mBackbuffer;
    bool mBound;
    bool mNeedsResolve;
    Gles mApi;
    std::string mExtensions;
    bool mQueriedExtensions;

    Display *mDisplay;
    bool mOwnsDisplay; // True if we created mDisplay
    GLXContext mContext;
    GLXContext mSharedContext;
    GLXPbuffer mPbuffer;
    GLXFBConfig mFBConfig;
};

// NB: We keep a reference the shared GL context, so "parent" context
//     must stay alive at least for the duration of this context.
//     We create "root" context for this purpose so it is satisfied.
//     TODO: Add assert/refcounting to enforce this.
GlesRendererImpl::GlesRendererImpl(GlesRendererImpl* shared_context)
        : mBound(false)
        , mNeedsResolve(false)
        , mDisplay(nullptr)
        , mContext(nullptr)
        , mSharedContext(shared_context != nullptr ? shared_context->mContext : 0)
        , mPbuffer(0) {

    if (shared_context != nullptr) {
        // Ensure that shared contexts also share X-display.
        // Drivers are know to misbehave/crash without this.
        // NB: This relies on the shared_context to stay alive.
        mDisplay = shared_context->mDisplay;
        mOwnsDisplay = false;
    } else {
        mDisplay = XOpenDisplay(nullptr);
        mOwnsDisplay = true;
        if (mDisplay == nullptr) {
            GAPID_FATAL("Unable to to open X display");
        }
    }

    int major;
    int minor;
    if (!glXQueryVersion(mDisplay, &major, &minor) || (major == 1 && minor < 3)) {
        GAPID_FATAL("GLX 1.3+ unsupported by X server (was %d.%d)", major, minor);
    }

    // Initialize with a default target.
    setBackbuffer(Backbuffer(
          8, 8,
          core::gl::GL_RGBA8,
          core::gl::GL_DEPTH24_STENCIL8,
          core::gl::GL_DEPTH24_STENCIL8));
}

GlesRendererImpl::~GlesRendererImpl() {
    reset();

    if (mOwnsDisplay && mDisplay != nullptr) {
        XCloseDisplay(mDisplay);
    }
}

Api* GlesRendererImpl::api() {
  return &mApi;
}

void GlesRendererImpl::reset() {
    unbind();

    if (mContext != nullptr) {
        glXDestroyContext(mDisplay, mContext);
        GAPID_DEBUG("Destroyed context %p", mContext);
        mContext = nullptr;
    }

    if (mPbuffer != 0) {
        glXDestroyPbuffer(mDisplay, mPbuffer);
{'fraction_non_alphanumeric': 0.09109182275011421, 'fraction_numerical': 0.021745089081772497, 'mean_word_length': 3.1368102796674227, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6179285', 'n_tokens_mistral': 3753, 'n_tokens_neox': 3564, 'n_words': 914}