PDA

View Full Version : Problem with DLL's and OpenGL



Mrwb
06-02-2005, 03:22 AM
Hi guys. :)

I have a problem with my graphics system. It's uses a plugin model, where plugins are loaded in run-time. The plugins contains graphic specific stuff, such as texture loaders, model loaders etc. Everything graphically is written in OpenGL, and reside in the plugins. The system itself (the exe file) only parses commands which executes plugin methods, and have no OpenGL code except clear and flip. The problem is; the system uses layers (it's for creating demos), and the layers get rendered in very non-logical ways. The render loop is simply a for loop going from 0 to layerCount, which passes commands from a layer stack to call the desired plugins. The thing is, I can't figure out why layer 0 isn't rendered first and layer 1 second etc. Instead, it seems almost like everything is rendered all at once. Stuff is drawn before I swap buffers, and color states and such ?¢_oleaks?¢__ onto the next layer (IE; if layer 1 contains the following; glColor3f(1,1,1) <some effect> glColor3f(0,0,0) there's a strong possibility that layer 2 gets set to white instead of black). I read up a bit, and it seems that DLL's are considered different processes than the main executables, something that would explain a lot, and also, it seems like the plugins are using multi-threading somehow. I asked around, and people told me that DLL's aren't multi-threaded, so I guess I can rule that one out though. The tool part of the system uses GLXTreem, while the player uses regular API calls.

The system uses a class called TdemoInstance, which contains a class holding the plugin methods and such. The plugin is loaded and accessed as the following code snippet shows:



type
TProc = procedure (params: PChar); StdCall; //this holds our dll procedure

type
RDLLMethod = record //this holds a custom procedure, and the name of the custom procedure.
Name: string;
Proc: TProc;
end;

procedure TPlugin.LoadPlugin(const Filename: Pchar); //this is the load DLL function
begin
LibHandle := LoadLibrary(Filename);
try
if LibHandle = 0 then //no lib found
begin
FLoaded := false;
exit;
end;
@FRun := GetProcAddress(LibHandle, 'ExecuteDLL'); //find the procedure Execute DLL in the loaded plugin, and store it in Frun. (a Tproc)
FName := Filename; //store the filename for future use
FLoaded := true;
finally
//
end;
end;

function TPlugin.plgWork(params: PChar): Pchar; //this function executes a DLL function
begin
if not (FLoaded) and (@FRun = nil) then
exit
else
FRun(params);
end;



Custom procedures are stored in an array of Tproc. The code above works perfectly.
Here's the render code:


GLXDraw1.Clear;
GLXCamera1.UpdatePosition(TranslateFirst);

if RenderScene.Checked then
DEditor.renderScene(FCurrentLayer);

if RenderDemo.Checked then
for x:=0 to DEditor.Layers.Count do
if (DEditor.Time>0) then
renderScene(x);

GLXDraw1.Flip;


renderScene is simply a for loop as outlined below:


for x:=0 to Deditor.Layers.Items[index].ContentCount do
RunLine(Deditor.Layers.Items[index].Content[x])


RunLine is the parser function, which only job is to execute the proper functions based on the command strings in Content[]. This also works as it's supposed to. I'm thinking that either the DLL's are running on separate processes, or there's something buggy with the OpenGL settings.

Any help would be greatly appreciated.

Paulius
06-02-2005, 10:20 AM
Most likely state restoration code never gets called, could you post more code how that glColor3f(1,1,1) <some effect> glColor3f(0,0,0) goes?

Mrwb
06-02-2005, 03:45 PM
Below is the code for a plugin used to display widescreen markers accross the screen.



library useless;

uses
Windows,
OpenGL;

function IntToStr(Num : Integer) : String; // using SysUtils increase file size by 100K
begin
Str(Num, result);
end;

function StrToInt(const S: string): Integer;
var
E: Integer;
begin
Val(S, Result, E);
end;

procedure do3d(params : pchar); stdCall;
begin
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
end;

procedure do2d(params : pchar); StdCall;
begin
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, 800, 600, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
end;

//-----------------------------------------


procedure drawWidescreenMarkers(params: PChar); StdCall;
begin
do2d('');
glColor3f(0,0,0);
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(800,0);
glVertex2f(800,75);
glVertex2f(0,75);
glEnd;

glBegin(GL_QUADS);
glVertex2f(0,515);
glVertex2f(800,515);
glVertex2f(800,600);
glVertex2f(0,600);
glEnd;
do3d('');
glColor3f(1,1,1);
end;



exports
drawWidescreenMarkers,
do3d,
do2d;

end.



This plugin is one of two which is written in delphi, the others are written in c++. All off them have problems with the things mentioned in the OP. (stuff leaking, rendering beeing rather chaotic despite the structure of the rendring loop etc) The golden rule of the plugin system is "all you enable you shall disable" so leaking is really wierd, seeing everything enabled by plugins, gets disabled by the plugins once they're done with their drawing..

Paulius
06-02-2005, 07:17 PM
Hmm, theres no ExecuteDLL exported in this library

Mrwb
06-02-2005, 08:11 PM
Actually, there is. But since it's empty, I diddn't include it in the pasting.. That function isn't used by all dll's, most of them have custom exported procedures. ExecuteDLL is a static proc, along with some ohter ones (freeing, init etc). But most of the plugins, (read; all) uses custom exported functions which can be anything. The custom procedures in libraries are working, stuff gets executed when it's intended, but somehow, the problems descibed earlier emerge. We've done some tests which shows that everything is rendered in the right order (going from layer 0 and up), but somehow, it seems like a plugin is on a different process than the main executable and hence, rendering gets a bit wierd. For instance, even though a procedure in the dll gets executed, the thing the procedure is drawing might not pop up on screen before the second rendering tick is complete.