Add mostly stubbed out GLX extensions
Surprisingly this lets most GLX apps run as they still render client side, they just need the extension to exist
This commit is contained in:
parent
6da9cb7362
commit
7088be0e51
|
|
@ -3,6 +3,7 @@ set(SOURCES
|
||||||
Base.cpp
|
Base.cpp
|
||||||
Extensions.cpp
|
Extensions.cpp
|
||||||
ExtBigReg.cpp
|
ExtBigReg.cpp
|
||||||
|
ExtGLX.cpp
|
||||||
ExtRANDR.cpp
|
ExtRANDR.cpp
|
||||||
Font.cpp
|
Font.cpp
|
||||||
Image.cpp
|
Image.cpp
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,427 @@
|
||||||
|
#include "Extensions.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/glxproto.h>
|
||||||
|
|
||||||
|
using BOOL32 = CARD32;
|
||||||
|
|
||||||
|
CARD32 g_fb_configs[2][24][2] {
|
||||||
|
{
|
||||||
|
{ GLX_FBCONFIG_ID, 1 },
|
||||||
|
{ GLX_VISUAL_ID, g_visual.visualID },
|
||||||
|
{ GLX_BUFFER_SIZE, 32 },
|
||||||
|
{ GLX_LEVEL, 0 },
|
||||||
|
{ GLX_DOUBLEBUFFER, True },
|
||||||
|
{ GLX_STEREO, False },
|
||||||
|
{ GLX_RENDER_TYPE, GLX_RGBA_BIT },
|
||||||
|
{ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT },
|
||||||
|
{ GLX_X_RENDERABLE, True },
|
||||||
|
{ GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR },
|
||||||
|
{ GLX_CONFIG_CAVEAT, GLX_NONE },
|
||||||
|
{ GLX_TRANSPARENT_TYPE, GLX_NONE },
|
||||||
|
{ GLX_RED_SIZE, 8 },
|
||||||
|
{ GLX_GREEN_SIZE, 8 },
|
||||||
|
{ GLX_BLUE_SIZE, 8 },
|
||||||
|
{ GLX_ALPHA_SIZE, 8 },
|
||||||
|
{ GLX_DEPTH_SIZE, 24 },
|
||||||
|
{ GLX_STENCIL_SIZE, 8 },
|
||||||
|
{ GLX_ACCUM_RED_SIZE, 0 },
|
||||||
|
{ GLX_ACCUM_GREEN_SIZE, 0 },
|
||||||
|
{ GLX_ACCUM_BLUE_SIZE, 0 },
|
||||||
|
{ GLX_ACCUM_ALPHA_SIZE, 0 },
|
||||||
|
{ GLX_SAMPLE_BUFFERS, 0 },
|
||||||
|
{ GLX_SAMPLES, 0 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ GLX_FBCONFIG_ID, 2 },
|
||||||
|
{ GLX_VISUAL_ID, g_visual.visualID },
|
||||||
|
{ GLX_BUFFER_SIZE, 32 },
|
||||||
|
{ GLX_LEVEL, 0 },
|
||||||
|
{ GLX_DOUBLEBUFFER, False },
|
||||||
|
{ GLX_STEREO, False },
|
||||||
|
{ GLX_RENDER_TYPE, GLX_RGBA_BIT },
|
||||||
|
{ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT },
|
||||||
|
{ GLX_X_RENDERABLE, True },
|
||||||
|
{ GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR },
|
||||||
|
{ GLX_CONFIG_CAVEAT, GLX_NONE },
|
||||||
|
{ GLX_TRANSPARENT_TYPE, GLX_NONE },
|
||||||
|
{ GLX_RED_SIZE, 8 },
|
||||||
|
{ GLX_GREEN_SIZE, 8 },
|
||||||
|
{ GLX_BLUE_SIZE, 8 },
|
||||||
|
{ GLX_ALPHA_SIZE, 8 },
|
||||||
|
{ GLX_DEPTH_SIZE, 24 },
|
||||||
|
{ GLX_STENCIL_SIZE, 8 },
|
||||||
|
{ GLX_ACCUM_RED_SIZE, 0 },
|
||||||
|
{ GLX_ACCUM_GREEN_SIZE, 0 },
|
||||||
|
{ GLX_ACCUM_BLUE_SIZE, 0 },
|
||||||
|
{ GLX_ACCUM_ALPHA_SIZE, 0 },
|
||||||
|
{ GLX_SAMPLE_BUFFERS, 0 },
|
||||||
|
{ GLX_SAMPLES, 0 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyGLXContext
|
||||||
|
{
|
||||||
|
CARD32 fbconfig;
|
||||||
|
BOOL is_direct;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BYTE s_glx_event_base;
|
||||||
|
static BYTE s_glx_error_base;
|
||||||
|
static BYTE s_glx_major_opcode;
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> extension_glx(Client& client_info, BAN::ConstByteSpan packet)
|
||||||
|
{
|
||||||
|
const uint8_t major_opcode = packet[0];
|
||||||
|
const uint8_t minor_opcode = packet[1];
|
||||||
|
|
||||||
|
const auto get_glx_context =
|
||||||
|
[&client_info, minor_opcode, major_opcode](CARD32 context) -> BAN::ErrorOr<MyGLXContext&>
|
||||||
|
{
|
||||||
|
auto it = g_objects.find(context);
|
||||||
|
if (it != g_objects.end() && it->value->type == Object::Type::Extension)
|
||||||
|
{
|
||||||
|
auto& ext = it->value->object.get<Object::Extension>();
|
||||||
|
if (ext.type_major == s_glx_major_opcode && ext.type_minor == GLXBadContext)
|
||||||
|
return *static_cast<MyGLXContext*>(ext.c_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
xError error {
|
||||||
|
.type = X_Error,
|
||||||
|
.errorCode = static_cast<BYTE>(s_glx_error_base + GLXBadContext),
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.resourceID = context,
|
||||||
|
.minorCode = minor_opcode,
|
||||||
|
.majorCode = major_opcode,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, error));
|
||||||
|
return BAN::Error::from_errno(ENOENT);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (minor_opcode)
|
||||||
|
{
|
||||||
|
case X_GLXCreateContext:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXCreateContextReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXCreateContext");
|
||||||
|
dprintln(" context: {}", request.context);
|
||||||
|
dprintln(" visual: {}", request.visual);
|
||||||
|
dprintln(" screen: {}", request.screen);
|
||||||
|
dprintln(" shareList: {}", request.shareList);
|
||||||
|
dprintln(" isDirect: {}", request.isDirect);
|
||||||
|
|
||||||
|
auto* object = new MyGLXContext({
|
||||||
|
.fbconfig = 1,
|
||||||
|
.is_direct = request.isDirect,
|
||||||
|
});
|
||||||
|
ASSERT(object);
|
||||||
|
|
||||||
|
TRY(client_info.objects.insert(request.context));
|
||||||
|
TRY(g_objects.insert(
|
||||||
|
request.context,
|
||||||
|
TRY(BAN::UniqPtr<Object>::create(Object {
|
||||||
|
.type = Object::Type::Extension,
|
||||||
|
.object = Object::Extension {
|
||||||
|
.type_major = s_glx_major_opcode,
|
||||||
|
.type_minor = GLXBadContext,
|
||||||
|
.c_private = object,
|
||||||
|
.destructor = [](Object::Extension& ext) { delete static_cast<MyGLXContext*>(ext.c_private); },
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXDestroyContext:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXDestroyContextReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXDestroyContext");
|
||||||
|
dprintln(" context: {}", request.context);
|
||||||
|
|
||||||
|
delete &TRY_REF(get_glx_context(request.context));
|
||||||
|
client_info.objects.remove(request.context);
|
||||||
|
g_objects.remove(request.context);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXIsDirect:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXIsDirectReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXIsDirect");
|
||||||
|
dprintln(" context: {}", request.context);
|
||||||
|
|
||||||
|
const auto& context = TRY_REF(get_glx_context(request.context));
|
||||||
|
|
||||||
|
xGLXIsDirectReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 0,
|
||||||
|
.isDirect = context.is_direct,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXQueryVersion:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXQueryVersionReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXQueryVersion");
|
||||||
|
dprintln(" majorVersion: {}", request.majorVersion);
|
||||||
|
dprintln(" minorVersion: {}", request.minorVersion);
|
||||||
|
|
||||||
|
xGLXQueryVersionReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 0,
|
||||||
|
.majorVersion = 1,
|
||||||
|
.minorVersion = 4,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXGetVisualConfigs:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXGetVisualConfigsReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXGetVisualConfigs");
|
||||||
|
dprintln(" screen: {}", request.screen);
|
||||||
|
|
||||||
|
xGLXGetVisualConfigsReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 1 * 18,
|
||||||
|
.numVisuals = 1,
|
||||||
|
.numProps = 18,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
TRY(encode<VISUALID>(client_info.output_buffer, g_visual.visualID));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, g_visual.c_class));
|
||||||
|
TRY(encode<BOOL32>(client_info.output_buffer, xTrue)); // rgba
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 8)); // red size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 8)); // green size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 8)); // blue size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 8)); // alpha size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 0)); // accum red size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 0)); // accum green size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 0)); // accum blue size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 0)); // accum alpha size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, xTrue)); // double buffer
|
||||||
|
TRY(encode<BOOL32>(client_info.output_buffer, xFalse)); // stereo
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 32)); // buffer size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 24)); // depth size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 8)); // stencil size
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 0)); // aux buffers
|
||||||
|
TRY(encode<INT32>(client_info.output_buffer, 0)); // level
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXQueryServerString:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXQueryServerStringReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXQueryServerString");
|
||||||
|
dprintln(" screen: {}", request.screen);
|
||||||
|
dprintln(" name: {}", request.name);
|
||||||
|
|
||||||
|
BAN::StringView string;
|
||||||
|
switch (request.name)
|
||||||
|
{
|
||||||
|
case GLX_VENDOR:
|
||||||
|
string = "XBANAN";
|
||||||
|
break;
|
||||||
|
case GLX_VERSION:
|
||||||
|
string = "1.4";
|
||||||
|
break;
|
||||||
|
case GLX_EXTENSIONS:
|
||||||
|
string = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
xGLXQueryServerStringReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = static_cast<CARD32>((string.size() + 3) / 4),
|
||||||
|
.n = static_cast<CARD16>(string.size()),
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
TRY(encode(client_info.output_buffer, string));
|
||||||
|
for (size_t i = 0; (string.size() + i) % 4; i++)
|
||||||
|
TRY(encode(client_info.output_buffer, '\0'));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXClientInfo:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXClientInfoReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXClientInfo");
|
||||||
|
dprintln(" major: {}", request.major);
|
||||||
|
dprintln(" minor: {}", request.minor);
|
||||||
|
dprintln(" extension: {}", BAN::StringView((char*)packet.data(), request.numbytes));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXGetFBConfigs:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXGetFBConfigsReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXGetFBConfigs");
|
||||||
|
dprintln(" screen: {}", request.screen);
|
||||||
|
|
||||||
|
constexpr size_t fbconfigs = sizeof(g_fb_configs) / sizeof(*g_fb_configs);
|
||||||
|
constexpr size_t attribs = sizeof(*g_fb_configs) / sizeof(**g_fb_configs);
|
||||||
|
|
||||||
|
xGLXGetFBConfigsReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 2 * fbconfigs * attribs,
|
||||||
|
.numFBConfigs = fbconfigs,
|
||||||
|
.numAttribs = attribs,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
TRY(encode(client_info.output_buffer, g_fb_configs));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXCreateNewContext:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXCreateNewContextReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXCreateNewContext");
|
||||||
|
dprintln(" context: {}", request.context);
|
||||||
|
dprintln(" fbconfig: {}", request.fbconfig);
|
||||||
|
dprintln(" screen: {}", request.screen);
|
||||||
|
dprintln(" renderType: {}", request.renderType);
|
||||||
|
dprintln(" shareList: {}", request.shareList);
|
||||||
|
dprintln(" isDirect: {}", request.isDirect);
|
||||||
|
|
||||||
|
auto* object = new MyGLXContext({
|
||||||
|
.fbconfig = request.fbconfig,
|
||||||
|
.is_direct = request.isDirect,
|
||||||
|
});
|
||||||
|
ASSERT(object);
|
||||||
|
|
||||||
|
TRY(client_info.objects.insert(request.context));
|
||||||
|
TRY(g_objects.insert(
|
||||||
|
request.context,
|
||||||
|
TRY(BAN::UniqPtr<Object>::create(Object {
|
||||||
|
.type = Object::Type::Extension,
|
||||||
|
.object = Object::Extension {
|
||||||
|
.type_major = s_glx_major_opcode,
|
||||||
|
.type_minor = GLXBadContext,
|
||||||
|
.c_private = object,
|
||||||
|
.destructor = [](Object::Extension& ext) { delete static_cast<MyGLXContext*>(ext.c_private); },
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXGetDrawableAttributes:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXGetDrawableAttributesReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXGetDrawableAttributes");
|
||||||
|
dprintln(" drawable: {}", request.drawable);
|
||||||
|
|
||||||
|
const auto& object = g_objects[request.drawable];
|
||||||
|
ASSERT(object->type == Object::Type::Window);
|
||||||
|
const auto& texture = object->object.get<Object::Window>().texture();
|
||||||
|
|
||||||
|
xGLXGetDrawableAttributesReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 2 * 6,
|
||||||
|
.numAttribs = 6,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, GLX_WIDTH));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, texture.width()));
|
||||||
|
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, GLX_HEIGHT));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, texture.height()));
|
||||||
|
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, GLX_PRESERVED_CONTENTS));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, xTrue));
|
||||||
|
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, GLX_LARGEST_PBUFFER));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, texture.width() * texture.height()));
|
||||||
|
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, GLX_FBCONFIG_ID));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 1));
|
||||||
|
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, GLX_EVENT_MASK));
|
||||||
|
TRY(encode<CARD32>(client_info.output_buffer, 0));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case X_GLXCreateWindow:
|
||||||
|
{
|
||||||
|
auto request = decode<xGLXCreateWindowReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("GLXCreateWindow");
|
||||||
|
dprintln(" screen: {}", request.screen);
|
||||||
|
dprintln(" fbconfig: {}", request.fbconfig);
|
||||||
|
dprintln(" window: {}", request.window);
|
||||||
|
dprintln(" glxwindow: {}", request.glxwindow);
|
||||||
|
dprintln(" numAttribs: {}", request.numAttribs);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < request.numAttribs; i++)
|
||||||
|
{
|
||||||
|
const auto key = decode<CARD32>(packet).value();
|
||||||
|
const auto value = decode<CARD32>(packet).value();
|
||||||
|
dprintln(" {} = {}", key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRY(client_info.objects.insert(request.glxwindow));
|
||||||
|
TRY(g_objects.insert(
|
||||||
|
request.glxwindow,
|
||||||
|
TRY(BAN::UniqPtr<Object>::create(Object {
|
||||||
|
.type = Object::Type::Extension,
|
||||||
|
.object = Object::Extension {
|
||||||
|
.type_major = s_glx_major_opcode,
|
||||||
|
.type_minor = GLXBadWindow,
|
||||||
|
.c_private = nullptr,
|
||||||
|
.destructor = [](Object::Extension&) { },
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
dwarnln("unsupported glx minor opcode {}", packet[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct GLXInstaller
|
||||||
|
{
|
||||||
|
GLXInstaller()
|
||||||
|
{
|
||||||
|
install_extension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, __GLX_NUMBER_ERRORS, extension_glx);
|
||||||
|
for (const auto& extension : g_extensions)
|
||||||
|
{
|
||||||
|
if (extension.name != GLX_EXTENSION_NAME)
|
||||||
|
continue;
|
||||||
|
s_glx_event_base = extension.event_base;
|
||||||
|
s_glx_error_base = extension.error_base;
|
||||||
|
s_glx_major_opcode = extension.major_opcode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} installer;
|
||||||
Loading…
Reference in New Issue