вторник, 4 сентября 2012 г.

GLScene 1.2 Ревизия 6122 Оптимизация достигнутого под Android

Приветствую! С решением проблемы каденсера стало возможным крупномасштабная оптимизация CustomDraw WidgetSet'a. Я позаимствовал класс TJNIEnv из модуля JEDI JNI для того что бы создать надстройку над всеми вызовами и упростить вызовы JNI, а так же убрать большое количества ненужных переменных. Что бы было понятно приведу кусок класса:
  TJNIEnv = class(TObject)
  public
    function JStringToString(JStr: JString): string;   
    function CallObjectMethod(Obj: JObject; MethodID: JMethodID ): JObject; overload;
    function CallObjectMethod(Obj: JObject; AClass: JClass;  const Name: PAnsiChar; const Sig: PAnsiChar ): JObject; overload;
    function CallObjectMethodV(Obj: JObject; MethodID: JMethodID; Args: va_list): JObject;
    function CallObjectMethodA(Obj: JObject; MethodID: JMethodID; Args: PJValue): JObject;   overload;
    function CallObjectMethodA(Obj: JObject; MethodID: JMethodID; const Args: array of const ): JObject;  overload;
    function CallObjectMethodA(Obj: JObject; AClass: JClass; const Name: PAnsiChar; const Sig: PAnsiChar; const Args: array of const ): JObject;  overload;  

Как видно из наличия перезагружаемых директив я немного дополнил методы своими, для упрощения части работы.


Так же я убрал все переменые, содержавшие яваID полей\методов, теперь поиск ID происходит непосредственно перед вызовом метода\поля, например:

var
  javaField_lclmajorversion: JfieldID=nil;
begin
  with javaVMRef.Env do
  begin
  javaField_lclmajorversion:= GetFieldID( javaActivityClass,   'lclmajorversion', 'I');
  self.MajorVersion := Integer(GetIntField( javaActivityObject, javaField_lclmajorversion)); 
 Так же позаимствовал класс ТjavaVM правда как я понял он изначально заточен для работы с самой явой и не годится для андроида, по этому большую часть этого кода я задефайнил позднее можно будет его применить если захотим вторгнутся в webGL или иные Java области.
Ну и переделал этот класс для работы с многопоточностью, что бы он мог выдавать нужный TJNIEnv для своего потока.

Так же весьма значительным я считаю возможность добавлять отладочную информацию непосредственно в логкат. Перед JNI вызовом происходит запись в LogCat о том что скоро произойдет вызов JNI. Пример реализации

function TJNIEnv.CallObjectMethod(Obj: JObject; MethodID: JMethodID ): JObject;
begin
  {$IFDEF jnidebug}
  __android_log_write(ANDROID_LOG_INFO, 'TJNIEnv', 'Call: CallObjectMethod');
  {$ENDIF}
  Result := Env^^.CallObjectMethod(Env, Obj, MethodID );
end; 

Это удобно в том плане что некоторые ошибки происходят при вызове JNI и LogCat показывает только ASM код, который вызывает больше вопросов чем ответов. Да, на java уровне, Java выдает достаточно детальную информацию о возникновении ошибки так же последовательность ее возникновения, однако в андроиде нету отладчика нативного кода и нативная библиотека может показать только область памяти что не приемлемо.
В первых пробах править виджетсет у меня такие ошибки вызывали лишь желание откатится назад! Но сейчас становится проще программировать так как знаешь что- где возникло ну или в каком месте следует искать.

Ну, вроде как с виджетсетом и каденсером разобрались осталось найти почему после сворачивания приложения и последующего развертывания нету рендеринга.

Ну чтож, это все, спасибо за внимание :)