Opened 2 years ago

Last modified 2 years ago

#13340 new bug

BGLView::GetGLProcAddress and eglGetProcAddress return NULL always

Reported by: waddlesplash Owned by: kallisti5
Priority: normal Milestone: Unscheduled
Component: Kits/OpenGL Kit Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Has a Patch: no Platform: All

Description

Encountered on x64 with Mesa 17.0.0-1. The Dolphin emulator's OpenGL system tries to get the address of glGetIntegerv, and both the official EGL system as well as the BGL backend I wrote for it return NULL when attempting to fetch the address of that function.

The complete port is here: https://github.com/waddlesplash/dolphin/tree/haiku

Note that if you want to use it, you'll need to change the "CPU Backend" to "Cached Interpreter" (the JIT is presently broken due to #13292), and enable logging (set log level to "Info", toggle all logging systems.)

Change History (2)

comment:1 Changed 2 years ago by Duggan

I can't find where in the Dolphin sources it calls cInterfaceBGL::Create() but I believe it calls GetGLProcAddress() either in the same function or at least in the same thread without break.

GetGLProcAddress() depends on the BGLDispatcher which is retrieved from the BGLRenderer(fRenderer)

void*
BGLView::GetGLProcAddress(const char* procName)
{
	BGLDispatcher* glDispatcher = NULL;

	if (fRenderer)
		glDispatcher = fRenderer->GLDispatcher();

	if (glDispatcher)
		return (void*)glDispatcher->AddressOf(procName);

	return NULL;
}

The renderer is not set until AttachedToWindow()

void
BGLView::AttachedToWindow()
{
	BView::AttachedToWindow();

	fBounds = Bounds();
	for (BView* view = this; view != NULL; view = view->Parent())
		view->ConvertToParent(&fBounds);

	fRenderer = fRoster->GetRenderer();
	if (fRenderer != NULL) {

while the GLRendererRoster it depends on is set in the constructor

BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
	ulong options)
	:
	BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
		//  | B_FULL_UPDATE_ON_RESIZE)
	fGc(NULL),
	fOptions(options),
	fDitherCount(0),
	fDrawLock("BGLView draw lock"),
	fDisplayLock("BGLView display lock"),
	fClipInfo(NULL),
	fRenderer(NULL),
	fRoster(NULL),
	fDitherMap(NULL)
{
	fRoster = new GLRendererRoster(this, options);
}

I don't know why fRenderer is not also set in the constructor, but I assume for a reason, perhaps to prevent unattached views from stealing CPU cycles. Regardless, if GetGLProcAddress() is called before the AttachedToWindow() callback has time to execute, fRenderer will be NULL, and as a result, GetGLProcAddress() will fail.

If this is indeed the case, the best solution may be to either inherit from BGLView and override the constructor and AttachedToWindow() functions, or it may just be easier (due to dependencies) to copy and paste the files and rename the class, changing the location of the one line... a little messy, but it should work fine.

The BGLView sources are located in the Mesa repo. If you need any additional help or if this doesn't solve the problem, let me know!

comment:2 Changed 2 years ago by waddlesplash

I don't know why fRenderer is not also set in the constructor, but I assume for a reason, perhaps to prevent unattached views from stealing CPU cycles. Regardless, if GetGLProcAddress() is called before the AttachedToWindow() callback has time to execute, fRenderer will be NULL, and as a result, GetGLProcAddress() will fail.

Since we define the behavior for BGLView, this might be OK (I'm inclined to think it is not, as offscreen BGLViews are completely legitimate, no?) but for EGL it is absolutely not OK; as EGL is a platform-independent API and must return values for eglGetProcAddr() even if the window init is not completely finished.

Note: See TracTickets for help on using tickets.