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
|
||||
Extensions.cpp
|
||||
ExtBigReg.cpp
|
||||
ExtGLX.cpp
|
||||
ExtRANDR.cpp
|
||||
Font.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