Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 12.12.2011, 17:10   #1
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
Вопрос Пишу модуль (gl3.pas) cтолкнулся с проблемой

Пишу модуль (gl3.pas) на основе OpenGL 3.3 Core Context Functionality
Cтолкнулся с проблемой, не получается получить указатели на ф-ии gl33 core.
К примеру.
Код:
procedure load_core_procs();
begin
  glActiveTexture:= gl_proc('glActiveTexture');
  glAttachShader:= gl_proc('glAttachShader');

  glBeginConditionalRender:= gl_proc('glBeginConditionalRender') ;
  glBeginQuery:= gl_proc('glBeginQuery');
  glBeginTransformFeedback:= gl_proc('glBeginTransformFeedback');
  glBindAttribLocation:= gl_proc('glBindAttribLocation');
  glBindBuffer:= gl_proc('glBindBuffer');
  glBindBufferBase:= gl_proc('glBindBufferBase');
  glBindBufferRange:= gl_proc('glBindBufferRange');
  glBindFragDataLocation:= gl_proc('glBindFragDataLocation');
  glBindFragDataLocationIndexed:= gl_proc('glBindFragDataLocationIndexed');
  glBindFramebuffer:= gl_proc('glBindFramebuffer');
  glBindRenderbuffer:= gl_proc('glBindRenderbuffer');
  glBindSampler:= gl_proc('glBindSampler');
  glBindTexture:= gl_proc('glBindTexture');
  glBindVertexArray:= gl_proc('glBindVertexArray');
  glBlendColor:= gl_proc('glBlendColor');
  glBlendEquation:= gl_proc('glBlendEquation');
  glBlendEquationSeparate:= gl_proc('glBlendEquationSeparate');
  glBlendFunc:= gl_proc('glBlendFunc');
...
Тогда как, на wgl – функции указатели получил.
Код:
procedure load_wgl_procs();
begin
  wglGetProcAddress	:= gl_proc('wglGetProcAddress');
  wglCreateContext 	:= gl_proc('wglCreateContext');
  wglDeleteContext	:= gl_proc('wglDeleteContext');
  wglMakeCurrent	:= gl_proc('wglMakeCurrent');
end;
Дрова 100% держат gl33. В чем может быть проблема?

может что-то я упустил в коде ф-й?
Код:
procedure load_lib();
begin
	if (gl_lib_handle<>0) then exit;
  gl_lib_handle := LoadLibraryA(PAnsiChar(OPENGL_LIBNAME));
  if (gl_lib_handle <>0) then gl_lib_is_loaded := true;

end;

procedure free_lib();
begin
  if (gl_lib_handle = 0) then exit;
  FreeLibrary(HMODULE(gl_lib_handle));
  gl_lib_handle:=0;
  gl_lib_is_loaded :=false;
end;

function gl_proc (const proc_name: PAnsiChar ):pointer;
begin
    result := GetProcAddress(HMODULE(gl_lib_handle), proc_name);

    if result <> nil then
    	exit;

    if Addr(wglGetProcAddress) <> nil then
      result := wglGetProcAddress(proc_name);
end;
Warn вне форума Ответить с цитированием
Старый 12.12.2011, 20:06   #2
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Разобрался.
Нужно было после получения адресов ф-й wgl создать контекст gl и только потом пытаться получать адреса ф-й ядра.
Warn вне форума Ответить с цитированием
Старый 15.12.2011, 08:42   #3
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Вновь возник вопрос.
Делегирую обработку сообщений от функции обработки сообщений
Код:
function WindowCallBack (const HWND, MSG, WPARAM, LPARAM : Longint ):Longint; stdcall;
var
	AppInst : PGLApp;
begin

  AppInst := PGLApp(Pointer(GetWindowLongPtrA(HWND, GWLP_USERDATA)));


  if (AppInst <> nil)
  then begin
  	Result := AppInst.MsgProc(HWND, MSG, WPARAM, LPARAM);
    exit;
  end;

  Result := DefWindowProc(HWND, MSG, WPARAM, LPARAM);
end;
К методу класса…

Код:
function TGLApp.MsgProc (const HWND, MSG, WPARAM, LPARAM : Longint ):Longint;
begin
case (msg) of
  	WM_QUIT, WM_DESTROY, WM_CLOSE :
    	begin
      	SetWindowLongA(HWND, GWL_USERDATA, 0);
      	PostQuitMessage(0);
        //IsActive := False;
    	end;
    // Секция кода обработки нажатий клавиш
    WM_KEYFIRST .. WM_KEYLAST:
    	begin

    	end;
    // Секция кода обработки событий мыши
    WM_MOUSEFIRST .. WM_MOUSELAST:
    	begin
      end;
    WM_ACTIVATE:
    	begin
      	IsActive := Boolean(LOWORD(WPARAM));
      end;
  end;

  Result := DefWindowProc(HWND, MSG, WPARAM, LPARAM);
end;
При этом возникает непонятная ошибка, если я не комментирую строчки с переменной IsActive (в function TGLApp.MsgProc). Т.е. ошибка возникает когда происходит обращение в полям класса. IsActive – это Boolean переменная в protected секции. Я не понимаю почему класс в нутрии своего метода MsgProc не может обращаться к своейже переменной IsActive ? wtf Oo?

Класс

Код:
type	TGLApp = class
protected
  Wc				: TWndClass;
  Msg 				: TMsg;
  AppInstance 			: HWnd;
  WindowHandle 			: HWnd;
  Width				: Integer;
  Height 			: Integer;
  IsActive			: Boolean;
  IsPaused			: Boolean;
  IsContextCreated		: Boolean;
  X, Y 				: Integer;
  rcView 			: TRect;
  WindowDC			: HDC;
  GLContext			: HGLRC;
  PixelBits			: Cardinal;
  DepthBits			: Cardinal;
  StencilBits			: Cardinal;
  WindowName			: PAnsiChar;

  function CreateWindowAndGLContext() : GLBoolean;

public

  function MsgProc (const HWND, MSG, WPARAM, LPARAM : Longint ):Longint;

  // События для потомков
  procedure OnUpdate(const fTime:GLfloat);	virtual;
  procedure OnRendering();	virtual;
  procedure OnMouse();		virtual;
  procedure OnKeyboard(); virtual;
  procedure OnStartup();	virtual;
  procedure OnCleanup();	virtual;

  procedure DoAppEvents();
  //procedure Quit();

  constructor Create(); overload;
  constructor Create(const _W, _H, _Bpp, _Depth, _Stencil:integer; const _WindowName:PAnsiChar); overload;

  destructor Destroy();override;
end;
PGLApp = ^TGLApp;
Warn вне форума Ответить с цитированием
Старый 15.12.2011, 09:10   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

объекты итак хранятся через ссылку, не нужно брать указатель от ссылки.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 15.12.2011, 09:52   #5
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Если про это
Цитата:
AppInst := PGLApp(Pointer(GetWindowLongPtrA(HW ND, GWLP_USERDATA)));
AppInst несовместим с integer который возвращает GetWindowLongPtrA, тут по другому не возможно Указатель на объект = указатель(адрес)

В отладке первоначально вижу класс в указателе AppInst, с реальными значениями переменных, все передается нормально, но вот потом после создания потомка класса(MyApp := MyGLApp.Create();), далее идет обработка сообщений (MyApp.DoAppEvents();), в AppInst поступает какойто мусор и он выполняет для мусорных данных TGLApp.MsgProc, тут все и начинается, на первом проходе обработчика сообщений.
Я тут подумал может обработчик обрабатывает "левые хендлы" окон и берет из них USERDATA и интерпретирует ее как класс, а далее пошло и поехало...?

Код:
program gl33test;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, gl3, gl3.app;


type MyGLApp = class(TGLApp)
  procedure OnRendering();override;
  constructor Create();
  destructor Destroy();override;

end;

constructor MyGLApp.Create();
begin
	inherited Create();

end;

destructor MyGLApp.Destroy();
begin
	inherited Destroy();

end;

procedure MyGLApp.OnRendering();
begin
  glClear(GL_COLOR_BUFFER_BIT);
  glClearColor(1,0,0,0);

  SwapBuffers(WindowDC);
end;



var
	MyApp	:	MyGLApp;
begin
  MyApp := MyGLApp.Create();
  MyApp.DoAppEvents();
  MyApp.Destroy();
end.
Если прикрепляю инст класса за хендлом окна так
Код:
SetWindowLongA(WindowHandle, GWL_USERDATA, HMODULE(@self));
получаю валидные данные тут
Код:
 AppInst := PGLApp(GetWindowLongA(HWND, GWLP_USERDATA));
Если же без взятия адреса класса
Код:
SetWindowLongA(WindowHandle, GWL_USERDATA, HMODULE(self));
получаю мусор тут
Код:
AppInst := PGLApp(GetWindowLongA(HWND, GWLP_USERDATA));

Последний раз редактировалось Warn; 15.12.2011 в 10:36.
Warn вне форума Ответить с цитированием
Старый 15.12.2011, 20:10   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Указатель на объект = указатель(адрес)
нет.
TClass это уже указатель на объект типа TClass, итого у вас выходит указатель на указатель на объект.
Цитата:
AppInst несовместим с integer который возвращает GetWindowLongPtrA
приведение типов ставьте и все ок.

бывала же тема про делегирование в ООП, посмотрите.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 15.12.2011, 20:52   #7
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Проблему решил.
Проблема была в том что строчка -
Код:
SetWindowLongA(WindowHandle, GWL_USERDATA, HMODULE(@self));
сидела в процедуре которую вызывал конструктор класса, и именно при таком размещении она вызывала (каким-то немыслимым образом) ошибки в WindowCallBack где AppInst был часто с мусорными данными, от сюда и ошибки в рунтайме.
т.е. так я понял, в конструкторе нельзя трогать и передавать куда либо @self, наверное, на этом этапе инст класса еще не определился со своим место положением в памяти

поэтому, вынес строчку из TGLApp.Create()->fn(); в самое начало TGLApp.DoAppEvents();
сохраняю так.
Код:
SetWindowLongA(WindowHandle, GWL_USERDATA, HMODULE(@self));
а беру так (с приведением типа).
Код:
function WindowCallBack (const HWND, MSG, WPARAM, LPARAM : Longint ):Longint; stdcall;
var
	AppInst : PGLApp;
begin
  AppInst := nil;
  AppInst := PGLApp(GetWindowLongA(HWND, GWLP_USERDATA));

  if (AppInst <> nil) then begin
  	Result := AppInst.MsgProc(HWND, MSG, WPARAM, LPARAM);
    exit;
  end else begin
  	Result := DefWindowProc(HWND, MSG, WPARAM, LPARAM);
    exit;
  end;

  result := 0;
end;
Все отлично работает, пока что)

Основной код программы.
Пока что инициализация gl33 core контекста
Код:
program gl33test;
{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, gl3, gl3.app;

type MyGLApp = class(TGLApp)
  function OnRendering() : GLBoolean; override;
  function OnStartup(): GLboolean; override;
  function OnCleanup(): GLboolean; override;
end;

function MyGLApp.OnStartup(): GLboolean;
begin
  Writeln('Load user resouces');
  Result := TRUE;
end;

function MyGLApp.OnCleanup(): GLboolean;
begin
 WriteLn('Cleanup user resoures');
 Result := TRUE;
end;

function MyGLApp.OnRendering():GLBoolean;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glClearColor(0,0,1,0);


  glFlush();
  Result := SwapBuffers(WindowDC);
end;

var
  MyApp	 : MyGLApp;
begin
  MyApp := MyGLApp.Create();
  MyApp.DoAppEvents();
  MyApp.Destroy();
  readln;
end.
Вложения
Тип файла: rar gl33test.rar (32.4 Кб, 8 просмотров)

Последний раз редактировалось Warn; 15.12.2011 в 21:02.
Warn вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите с проблемой!? fandorn Microsoft Office Excel 1 18.11.2009 04:37
помогите с проблемой vaso1983 Gamedev - cоздание игр: Unity, OpenGL, DirectX 2 28.04.2009 20:52
Как подключить к проекту модуль ras.pas Михаил Юрьевич Общие вопросы Delphi 3 14.03.2009 15:45
Делаю сайты, пишу маленькие/большие скрипты. Пишу веб-приложения и приложения под Windows. SkyM@n Фриланс 3 29.12.2007 16:21