diff --git a/.gitignore b/.gitignore index 296cd6a..a2e661e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ .project *.bat *.sis +*.sisx +*.d ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. diff --git a/group/bld.inf b/group/bld.inf index c4c8c5c..6f421bc 100644 --- a/group/bld.inf +++ b/group/bld.inf @@ -3,6 +3,7 @@ DEFAULT ARMV6 PRJ_MMPFILES gnumakefile shaders.mk -gnumakefile Icons_scalable_dc.mk -librw.mmp -re3.mmp +//librw_gles2.mmp +//re3_gles2.mmp +librw_gles1.mmp +re3_gles1.mmp diff --git a/group/common.mmh b/group/common.mmh index aa91247..41dd5ec 100644 --- a/group/common.mmh +++ b/group/common.mmh @@ -1,16 +1,12 @@ SYSTEMINCLUDE /epoc32/include -SYSTEMINCLUDE /epoc32/include/stdapis/stlportv5 SYSTEMINCLUDE /epoc32/include/stdapis SYSTEMINCLUDE /epoc32/include/mw SYSTEMINCLUDE /epoc32/include/platform SYSTEMINCLUDE /epoc32/include/platform/mw -SYSTEMINCLUDE /epoc32/include/gles USERINCLUDE . MACRO LIBRW -MACRO RW_GL3 -MACRO RW_OPENGL // because carbide is too stupid MACRO MASTER DEBUGGABLE @@ -26,4 +22,13 @@ OPTION_REPLACE ARMCC -O2 -O3 ALWAYS_BUILD_AS_ARM #endif +#ifdef SYMBIAN_3 +SYSTEMINCLUDE /epoc32/include/stdapis/stlportv5 STDCPP +MACRO RW_GL3 +#else +SYSTEMINCLUDE /epoc32/include/stdapis/stlport +SYSTEMINCLUDE /epoc32/include/stdapis/stlport/stl +MACRO RW_GLES1 +MACRO S60V5 +#endif diff --git a/group/librw.mmp b/group/librw.mmh similarity index 89% rename from group/librw.mmp rename to group/librw.mmh index b7f216c..b38f518 100644 --- a/group/librw.mmp +++ b/group/librw.mmh @@ -1,9 +1,7 @@ #include "common.mmh" -TARGET librw.lib TARGETTYPE lib - USERINCLUDE ../vendor/librw USERINCLUDE ../vendor/librw/src @@ -15,6 +13,8 @@ SOURCEPATH ../vendor/librw/src SOURCE engine.cpp error.cpp frame.cpp geometry.cpp geoplg.cpp SOURCEPATH ../vendor/librw/src/gl SOURCE gl3.cpp gl3device.cpp gl3immed.cpp gl3matfx.cpp gl3pipe.cpp gl3raster.cpp gl3render.cpp gl3shader.cpp gl3skin.cpp wdgl.cpp +SOURCEPATH ../vendor/librw/src/gles1 +SOURCE gl1.cpp gl1device.cpp gl1immed.cpp gl1matfx.cpp gl1pipe.cpp gl1raster.cpp gl1render.cpp gl1skin.cpp SOURCEPATH ../vendor/librw/src SOURCE hanim.cpp image.cpp light.cpp SOURCEPATH ../vendor/librw/src/lodepng diff --git a/group/librw_gles1.mmp b/group/librw_gles1.mmp new file mode 100644 index 0000000..0ed82e4 --- /dev/null +++ b/group/librw_gles1.mmp @@ -0,0 +1,4 @@ +#undef SYMBIAN3 +#define S60V3 +TARGET librw_gles1.lib +#include "librw.mmh" \ No newline at end of file diff --git a/group/librw_gles2.mmp b/group/librw_gles2.mmp new file mode 100644 index 0000000..b161ff5 --- /dev/null +++ b/group/librw_gles2.mmp @@ -0,0 +1,4 @@ +#undef S60V3 +#define SYMBIAN_3 +TARGET librw_gles2.lib +#include "librw.mmh" \ No newline at end of file diff --git a/group/re3.mmp b/group/re3.mmh similarity index 97% rename from group/re3.mmp rename to group/re3.mmh index 40d61b8..200c71a 100644 --- a/group/re3.mmp +++ b/group/re3.mmh @@ -1,29 +1,22 @@ #include "common.mmh" -TARGET re3.exe TARGETTYPE exe UID 0 0xe0d67647 LIBRARY euser.lib -LIBRARY libstdcppv5.lib LIBRARY libc.lib LIBRARY libm.lib LIBRARY libpthread.lib -LIBRARY libglesv2.lib -LIBRARY libegl.lib LIBRARY apparc.lib LIBRARY cone.lib LIBRARY eikcore.lib LIBRARY avkon.lib LIBRARY ws32.lib LIBRARY hal.lib -LIBRARY platformver.lib EPOCSTACKSIZE 0x14000 EPOCHEAPSIZE 0x80000 0x4000000 -STATICLIBRARY librw.lib - SYSTEMINCLUDE ../vendor/librw SOURCEPATH . diff --git a/group/re3_gles1.mmp b/group/re3_gles1.mmp new file mode 100644 index 0000000..690f1b2 --- /dev/null +++ b/group/re3_gles1.mmp @@ -0,0 +1,9 @@ +#undef SYMBIAN_3 +#define S60V3 +//TARGET re3_gles1.exe +TARGET re3.exe +LIBRARY libstdcpp.lib +LIBRARY libgles_cm.lib +STATICLIBRARY librw_gles1.lib +ARMFPU softvfp +#include "re3.mmh" \ No newline at end of file diff --git a/group/re3_gles2.mmp b/group/re3_gles2.mmp new file mode 100644 index 0000000..258d08b --- /dev/null +++ b/group/re3_gles2.mmp @@ -0,0 +1,10 @@ +#undef S60V3 +#define SYMBIAN_3 +TARGET re3_gles2.exe +LIBRARY libstdcppv5.lib +LIBRARY libglesv2.lib +LIBRARY libegl.lib +LIBRARY platformver.lib +STATICLIBRARY librw_gles2.lib +ARMFPU softvfp+vfpv2 +#include "re3.mmh" \ No newline at end of file diff --git a/group/shaders.mk b/group/shaders.mk index 7e321f2..4114b29 100644 --- a/group/shaders.mk +++ b/group/shaders.mk @@ -5,17 +5,16 @@ do_nothing : MAKMAKE: do_nothing -BLD: do_nothing +BLD: + $(MAKE) -C ../vendor/librw/src/gl/shaders/ -f Makefile all -CLEAN: - rm ../vendor/librw/src/gl/shaders/*.inc +CLEAN: do_nothing LIB: do_nothing CLEANLIB: do_nothing -RESOURCE: - $(MAKE) -C ../vendor/librw/src/gl/shaders/ -f Makefile all +RESOURCE: do_nothing FREEZE: do_nothing diff --git a/sis/incompatible_openc.txt b/sis/incompatible_openc.txt new file mode 100644 index 0000000..29b844d --- /dev/null +++ b/sis/incompatible_openc.txt @@ -0,0 +1 @@ +OpenC version 1.5 or later is required for installation. \ No newline at end of file diff --git a/sis/re3.pkg b/sis/re3.pkg index 0d9811b..62cc2e5 100644 --- a/sis/re3.pkg +++ b/sis/re3.pkg @@ -1,10 +1,21 @@ #{"GTA III"},(0xe0d67647),1,0,0 +[0x101F7961], 0, 0, 0, {"S60ProductID"} +[0x1028315F], 0, 0, 0, {"S60ProductID"} [0x20022E6D], 0, 0, 0, {"S60ProductID"} %{"nnproject"} :"nnproject" +;IF (NOT package(0x20009A80)) OR (NOT package(0x2002372A)) ; old or missing openc +; "incompatible_openc.txt"-"", FT, FORCEABORT +;ENDIF + +;IF exists("z:\system\install\Series60v5.2.sis") AND exists("z:\sys\bin\libGLESv2.dll") +; "$(EPOCROOT)epoc32\release\$(PLATFORM)\$(TARGET)\re3_gles2.exe"-"!:\sys\bin\re3.exe" +;ELSE +; "$(EPOCROOT)epoc32\release\$(PLATFORM)\$(TARGET)\re3_gles1.exe"-"!:\sys\bin\re3.exe" +;ENDIF "$(EPOCROOT)epoc32\release\$(PLATFORM)\$(TARGET)\re3.exe"-"!:\sys\bin\re3.exe" "$(EPOCROOT)\epoc32\data\z\private\10003a3f\import\apps\re3_reg.rsc" - "!:\private\10003a3f\import\apps\re3_reg.rsc" "$(EPOCROOT)\epoc32\data\z\resource\apps\re3.rsc" - "!:\resource\apps\re3.rsc" diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h index 45720b6..8f90453 100644 --- a/src/animation/AnimBlendAssociation.h +++ b/src/animation/AnimBlendAssociation.h @@ -84,7 +84,7 @@ public: inline float GetTimeLeft() { return hierarchy->totalLength - currentTime; } static CAnimBlendAssociation *FromLink(CAnimBlendLink *l) { - return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link)); + return (CAnimBlendAssociation*)((uint8*)l - OFFSET_OF(CAnimBlendAssociation, link)); } }; diff --git a/src/animation/AnimBlendHierarchy.h b/src/animation/AnimBlendHierarchy.h index 40d2731..ed9d244 100644 --- a/src/animation/AnimBlendHierarchy.h +++ b/src/animation/AnimBlendHierarchy.h @@ -30,4 +30,4 @@ public: void MoveMemory(bool onlyone = false); }; -VALIDATE_SIZE(CAnimBlendHierarchy, 0x28); \ No newline at end of file +VALIDATE_SIZE(CAnimBlendHierarchy, 0x28); diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h index baf6eb3..8e36830 100644 --- a/src/animation/AnimationId.h +++ b/src/animation/AnimationId.h @@ -207,4 +207,4 @@ enum AnimationId ANIM_STD_PHONE_TALK, ANIM_STD_NUM -}; \ No newline at end of file +}; diff --git a/src/audio/sampman.h b/src/audio/sampman.h index ad14e2b..3d10ed1 100644 --- a/src/audio/sampman.h +++ b/src/audio/sampman.h @@ -670,4 +670,4 @@ static char StreamedNameTable[][25] = "AUDIO\\k1_b.WAV", "AUDIO\\cat1.WAV" }; -#endif \ No newline at end of file +#endif diff --git a/src/collision/ColBox.h b/src/collision/ColBox.h index ac2cd67..69129b1 100644 --- a/src/collision/ColBox.h +++ b/src/collision/ColBox.h @@ -13,4 +13,4 @@ struct CColBox CVector GetSize(void) { return max - min; } CColBox& operator=(const CColBox &other); -}; \ No newline at end of file +}; diff --git a/src/collision/ColLine.h b/src/collision/ColLine.h index 21587a0..f66a48b 100644 --- a/src/collision/ColLine.h +++ b/src/collision/ColLine.h @@ -11,4 +11,4 @@ struct CColLine CColLine(void) { }; CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; }; void Set(const CVector &p0, const CVector &p1); -}; \ No newline at end of file +}; diff --git a/src/collision/ColModel.h b/src/collision/ColModel.h index 7dcdfa4..daae720 100644 --- a/src/collision/ColModel.h +++ b/src/collision/ColModel.h @@ -34,4 +34,4 @@ struct CColModel void GetTrianglePoint(CVector &v, int i) const; CColModel& operator=(const CColModel& other); -}; \ No newline at end of file +}; diff --git a/src/collision/ColSphere.h b/src/collision/ColSphere.h index 70e2976..2608837 100644 --- a/src/collision/ColSphere.h +++ b/src/collision/ColSphere.h @@ -10,4 +10,4 @@ struct CColSphere uint8 surface; uint8 piece; void Set(float radius, const CVector ¢er, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0); -}; \ No newline at end of file +}; diff --git a/src/collision/ColTriangle.h b/src/collision/ColTriangle.h index 9e918e3..5e1bc81 100644 --- a/src/collision/ColTriangle.h +++ b/src/collision/ColTriangle.h @@ -65,4 +65,4 @@ struct CColTrianglePlane void GetNormal(CVector &n) const { n = normal; } float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; }; #endif -}; \ No newline at end of file +}; diff --git a/src/collision/CompressedVector.h b/src/collision/CompressedVector.h index d54e49b..1a75aad 100644 --- a/src/collision/CompressedVector.h +++ b/src/collision/CompressedVector.h @@ -33,4 +33,4 @@ struct CompressedVector CVector Get(void) const { return CVector(x, y, z); }; void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; }; #endif -}; \ No newline at end of file +}; diff --git a/src/core/Accident.h b/src/core/Accident.h index 568e114..514968f 100644 --- a/src/core/Accident.h +++ b/src/core/Accident.h @@ -28,4 +28,4 @@ public: bool WorkToDoForMedics(); }; -extern CAccidentManager gAccidentManager; \ No newline at end of file +extern CAccidentManager gAccidentManager; diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp index 33662ac..69bba28 100644 --- a/src/core/ControllerConfig.cpp +++ b/src/core/ControllerConfig.cpp @@ -43,7 +43,7 @@ void CControllerConfigManager::MakeControllerActionsBlank() } } -#ifdef RW_GL3 +#if defined RW_GL3 || defined RW_GLES1 int MapIdToButtonId(int mapId) { #ifdef __SYMBIAN32__ // TODO @@ -102,7 +102,7 @@ int32 CControllerConfigManager::GetJoyButtonJustDown() if (m_NewState.rgbButtons[i] & 0x80 && !(m_OldState.rgbButtons[i] & 0x80)) return i + 1; } -#elif defined RW_GL3 +#elif defined RW_GL3 || defined RW_GLES1 if (m_NewState.isGamepad) { for (int32 i = 0; i < MAX_BUTTONS; i++) { if (m_NewState.mappedButtons[i] && !(m_OldState.mappedButtons[i])) @@ -2773,7 +2773,7 @@ void CControllerConfigManager::UpdateJoyButtonState(int32 padnumber) else m_aButtonStates[i] = false; } -#elif defined RW_GL3 +#elif defined RW_GL3 || defined RW_GLES1 if (m_NewState.isGamepad) { for (int32 i = 0; i < MAX_BUTTONS; i++) { #if !defined __SYMBIAN32__ diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h index 295f03b..814bab2 100644 --- a/src/core/ControllerConfig.h +++ b/src/core/ControllerConfig.h @@ -103,7 +103,7 @@ class CControllerState; #define ACTIONNAME_LENGTH 40 -#ifdef RW_GL3 +#if defined RW_GL3 || defined RW_GLES1 struct GlfwJoyState { int8 id; bool isGamepad; @@ -129,7 +129,7 @@ public: }; bool m_bFirstCapture; -#if defined RW_GL3 +#if defined RW_GL3 || defined RW_GLES1 GlfwJoyState m_OldState; GlfwJoyState m_NewState; #else @@ -219,8 +219,8 @@ public: void ResetSettingOrder (e_ControllerAction action); }; -#ifndef RW_GL3 +#if !defined RW_GL3 && !defined RW_GLES1 VALIDATE_SIZE(CControllerConfigManager, 0x143C); #endif -extern CControllerConfigManager ControlsManager; \ No newline at end of file +extern CControllerConfigManager ControlsManager; diff --git a/src/core/EventList.h b/src/core/EventList.h index 4ced3a8..7cc3a61 100644 --- a/src/core/EventList.h +++ b/src/core/EventList.h @@ -62,4 +62,4 @@ public: static void ReportCrimeForEvent(eEventType type, intptr, bool); }; -extern CEvent gaEvent[NUMEVENTS]; \ No newline at end of file +extern CEvent gaEvent[NUMEVENTS]; diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 2328075..e5c6dd7 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -5138,7 +5138,7 @@ CMenuManager::ProcessButtonPresses(void) ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); ControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp()); -#if !defined RW_GL3 +#if !defined RW_GL3 && !defined RW_GLES1 if (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) { DIDEVCAPS devCaps; devCaps.dwSize = sizeof(DIDEVCAPS); diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index b29c19e..6918c3f 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -1124,7 +1124,7 @@ CRadar::LoadTextures() || (x2 < 1 && y2 == 1)) // one pixel on each side of second to first/last line is transparent pixels[x + y * 16] = 0; else if((x2 == 2 && y2 >= 2)|| (y2 == 2 && x2 >= 2) )// colored square inside -#ifdef RW_GL3 +#if defined RW_GL3 || defined RW_GLES1 pixels[x + y * 16] = WAYPOINT_R | (WAYPOINT_G << 8) | (WAYPOINT_B << 16) | (255 << 24); #else pixels[x + y * 16] = WAYPOINT_B | (WAYPOINT_G << 8) | (WAYPOINT_R << 16) | (255 << 24); diff --git a/src/core/Range2D.h b/src/core/Range2D.h index f239e7d..bd13e56 100644 --- a/src/core/Range2D.h +++ b/src/core/Range2D.h @@ -8,4 +8,4 @@ public: bool IsInRange(CVector2D vec); void DebugShowRange(float, int); CVector2D GetRandomPointInRange(); -}; \ No newline at end of file +}; diff --git a/src/core/common.h b/src/core/common.h index d8e795b..f781b76 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -354,7 +354,7 @@ __inline__ void TRACE(char *f, ...) { } // this is re3 only, and so the function #else #define debug(f, ...) re3_debug("[DBG]: " f, ## __VA_ARGS__) #define Error(f, ...) re3_debug("[ERROR]: " f, ## __VA_ARGS__) -#ifndef MASTER +#if !defined MASTER || defined LOGS #define TRACE(f, ...) re3_trace(__FILE__, __LINE__, __FUNCTION__, f, ## __VA_ARGS__) #define USERERROR(f, ...) re3_usererror(f, ## __VA_ARGS__) #else @@ -367,7 +367,7 @@ __inline__ void TRACE(char *f, ...) { } // this is re3 only, and so the function #undef ASSERT #endif -#ifndef MASTER +#if !defined MASTER || defined LOGS #define assert(_Expression) (void)( (!!(_Expression)) || (re3_assert(#_Expression, __FILE__, __LINE__, __FUNCTION__), 0) ) #else #define assert(_Expression) (_Expression) diff --git a/src/core/config.h b/src/core/config.h index 7b789e4..05f9a1a 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,5 +1,8 @@ #pragma once +#define LOGS +#define LOGS_RDEBUG + // disables (most) stuff that wasn't in original gta3.exe #ifdef __MWERKS__ #define VANILLA_DEFINES diff --git a/src/core/main.cpp b/src/core/main.cpp index 436de8f..f77ed49 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1140,6 +1140,8 @@ DisplayGameDebugText() "D3D8 " #elif defined RW_GL3 "OpenGL " +#elif defined RW_GLES1 + "GLES1 " #endif #if defined AUDIO_OAL "OAL " @@ -1633,7 +1635,7 @@ Idle(void *arg) if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) && TheCamera.GetScreenFadeStatus() != FADE_2) { -#if defined(GTA_PC) && !defined(RW_GL3) && defined(FIX_BUGS) +#if defined(GTA_PC) && !defined(RW_GL3) && !defined(RW_GLES1) && defined(FIX_BUGS) // This is from SA, but it's nice for windowed mode if (!FrontEndMenuManager.m_bRenderGameInMenu) { RwV2d pos; diff --git a/src/core/re3.cpp b/src/core/re3.cpp index fd6f437..c4cd2c3 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -69,7 +69,7 @@ myrand(void) { #ifdef USE_PS2_RAND // Use our own implementation of rand, stolen from PS2 - myrand_seed = 0x5851F42D4C957F2D * myrand_seed + 1; + myrand_seed = 0x5851F42D4C957F2DULL * myrand_seed + 1; return ((myrand_seed >> 32) & 0x7FFFFFFF); #else // or original codewarrior rand @@ -1105,12 +1105,12 @@ extern bool gbRenderWorld2; #endif #ifndef __MWERKS__ -#ifndef MASTER +#if !defined MASTER || defined LOGS const int re3_buffsize = 1024; static char re3_buff[re3_buffsize]; #endif -#ifndef MASTER +#if !defined MASTER || defined LOGS void re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func) { #ifdef _WIN32 @@ -1166,9 +1166,13 @@ void re3_assert(const char *expr, const char *filename, unsigned int lineno, con } #endif +#ifdef LOGS_RDEBUG +extern "C" void RDebug_Printf(const char*, ...); +#endif + void re3_debug(const char *format, ...) { -#ifndef MASTER +#if !defined MASTER || defined LOGS va_list va; va_start(va, format); #ifdef _WIN32 @@ -1179,11 +1183,15 @@ void re3_debug(const char *format, ...) va_end(va); printf("%s", re3_buff); +#ifdef LOGS_RDEBUG + RDebug_Printf("%s", re3_buff); +#else CDebug::DebugAddText(re3_buff); #endif +#endif } -#ifndef MASTER +#if !defined MASTER || defined LOGS void re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...) { char buff[re3_buffsize *2]; @@ -1205,7 +1213,7 @@ void re3_trace(const char *filename, unsigned int lineno, const char *func, cons } #endif -#ifndef MASTER +#if !defined MASTER || defined LOGS void re3_usererror(const char *format, ...) { va_list va; diff --git a/src/extras/debugmenu.h b/src/extras/debugmenu.h index 45b65d0..f52d75d 100644 --- a/src/extras/debugmenu.h +++ b/src/extras/debugmenu.h @@ -201,4 +201,4 @@ inline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, { return DebugMenuAddVarBool8(path, name, (int8_t*)ptr, triggerFunc); } -#endif \ No newline at end of file +#endif diff --git a/src/math/Matrix.cpp b/src/math/Matrix.cpp index b11e8a1..01c4197 100644 --- a/src/math/Matrix.cpp +++ b/src/math/Matrix.cpp @@ -541,4 +541,4 @@ CCompressedMatrixNotAligned::DecompressIntoFullMatrix(CMatrix &other) other.GetUp() = CrossProduct(other.GetRight(), other.GetForward()); other.GetPosition() = m_vecPos; other.Reorthogonalise(); -} \ No newline at end of file +} diff --git a/src/math/Quaternion.cpp b/src/math/Quaternion.cpp index b0e782e..6128f58 100644 --- a/src/math/Quaternion.cpp +++ b/src/math/Quaternion.cpp @@ -174,4 +174,4 @@ CQuaternion::Set(float f1, float f2, float f3) y = ((s1 * c2) * c3) + ((s2 * c1) * s3); z = ((s2 * c1) * c3) - ((s1 * c2) * s3); w = ((c2 * c1) * c3) + ((s2 * s1) * s3); -} \ No newline at end of file +} diff --git a/src/math/Rect.cpp b/src/math/Rect.cpp index de6320a..8b41dc2 100644 --- a/src/math/Rect.cpp +++ b/src/math/Rect.cpp @@ -14,4 +14,4 @@ CRect::CRect(float l, float t, float r, float b) top = t; right = r; bottom = b; -} \ No newline at end of file +} diff --git a/src/math/Vector.h b/src/math/Vector.h index 776bfcf..a25cd74 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -126,4 +126,4 @@ class CMatrix; CVector Multiply3x3(const CMatrix &mat, const CVector &vec); CVector Multiply3x3(const CVector &vec, const CMatrix &mat); -CVector operator*(const CMatrix &mat, const CVector &vec); \ No newline at end of file +CVector operator*(const CMatrix &mat, const CVector &vec); diff --git a/src/math/math.cpp b/src/math/math.cpp index 8cb56da..57d6f82 100644 --- a/src/math/math.cpp +++ b/src/math/math.cpp @@ -80,7 +80,8 @@ void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, ": : "r" (out) , "r" (n), "r" (&mat), "r" (in), "r" (stride): "memory"); #else while(n--){ - *out = mat * *in; + const RwV3d i = *in; + *out = mat * i; in = (RwV3d*)((uint8*)in + stride); out++; } @@ -110,7 +111,8 @@ void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector ": : "r" (out) , "r" (n), "r" (&mat) ,"r" (in): "memory"); #else while(n--){ - *out = mat * *in; + const RwV3d i = *in; + *out = mat * i; in++; out++; } diff --git a/src/modelinfo/MloModelInfo.h b/src/modelinfo/MloModelInfo.h index b1ae329..f2bafc8 100644 --- a/src/modelinfo/MloModelInfo.h +++ b/src/modelinfo/MloModelInfo.h @@ -11,4 +11,4 @@ public: public: CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {} void ConstructClump(); -}; \ No newline at end of file +}; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index c0f0192..be7389c 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -506,4 +506,4 @@ IsFence(int16 id) { return id == MI_FENCE || id == MI_FENCE2; -} \ No newline at end of file +} diff --git a/src/modelinfo/PedModelInfo.h b/src/modelinfo/PedModelInfo.h index 26ab3c3..b6c9d12 100644 --- a/src/modelinfo/PedModelInfo.h +++ b/src/modelinfo/PedModelInfo.h @@ -64,4 +64,4 @@ public: }; #ifndef PED_SKIN VALIDATE_SIZE(CPedModelInfo, 0x48); -#endif \ No newline at end of file +#endif diff --git a/src/modelinfo/XtraCompsModelInfo.h b/src/modelinfo/XtraCompsModelInfo.h index ab308a8..a6fe5f6 100644 --- a/src/modelinfo/XtraCompsModelInfo.h +++ b/src/modelinfo/XtraCompsModelInfo.h @@ -10,4 +10,4 @@ public: void Shutdown(void) {}; RwObject *CreateInstance(void) { return nil; } void SetClump(RpClump*) {}; -}; \ No newline at end of file +}; diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 1c4f10f..63f8e09 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -464,4 +464,4 @@ CPed::RunToReportCrime(eCrimeType crimeToReport) m_phoneId = phoneId; m_crimeToReportOnPhone = crimeToReport; return true; -} \ No newline at end of file +} diff --git a/src/peds/PedChat.cpp b/src/peds/PedChat.cpp index 907f575..a89ab6a 100644 --- a/src/peds/PedChat.cpp +++ b/src/peds/PedChat.cpp @@ -149,4 +149,4 @@ CPed::Say(uint16 audio) m_queuedSound = audio; } } -} \ No newline at end of file +} diff --git a/src/peds/PedDebug.cpp b/src/peds/PedDebug.cpp index 1c22963..f78502d 100644 --- a/src/peds/PedDebug.cpp +++ b/src/peds/PedDebug.cpp @@ -307,4 +307,4 @@ CPed::DebugRenderClosePedText() { // TODO: mobile code } -#endif \ No newline at end of file +#endif diff --git a/src/peds/PedPlacement.h b/src/peds/PedPlacement.h index b51e2aa..66dbcc6 100644 --- a/src/peds/PedPlacement.h +++ b/src/peds/PedPlacement.h @@ -5,4 +5,4 @@ public: static void FindZCoorForPed(CVector* pos); static CEntity* IsPositionClearOfCars(Const CVector*); static bool IsPositionClearForPed(CVector*); -}; \ No newline at end of file +}; diff --git a/src/peds/PedType.h b/src/peds/PedType.h index 3e23c24..414585e 100644 --- a/src/peds/PedType.h +++ b/src/peds/PedType.h @@ -170,4 +170,4 @@ public: static ePedStats GetPedStatType(char *name); }; -VALIDATE_SIZE(CPedStats, 0x34); \ No newline at end of file +VALIDATE_SIZE(CPedStats, 0x34); diff --git a/src/renderer/Console.h b/src/renderer/Console.h index 9f22236..ee37021 100644 --- a/src/renderer/Console.h +++ b/src/renderer/Console.h @@ -24,4 +24,4 @@ public: extern CConsole TheConsole; -void cprintf(char*, ...); \ No newline at end of file +void cprintf(char*, ...); diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h index 0e04aec..a882022 100644 --- a/src/rw/RwHelper.h +++ b/src/rw/RwHelper.h @@ -60,4 +60,4 @@ void RestoreAlphaTest(); #else #define SetAlphaTest(a) (0) #define RestoreAlphaTest() (0) -#endif \ No newline at end of file +#endif diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp index bbfee01..ed78919 100644 --- a/src/rw/TexRead.cpp +++ b/src/rw/TexRead.cpp @@ -93,36 +93,106 @@ static int clamp(int size, int targetSize) return size; } -static void downscaleTexture(RwTexture *texture) -{ - RwRaster *oldRaster = RwTextureGetRaster(texture); - if (oldRaster == nil) - return; +void debugRaster(RwRaster *r){ + if(!r){ + debug("Raster NULL"); + return; + } - extern bool moreVram; - int targetSize = moreVram ? 64 : 32; - - int oldWidth = RwRasterGetWidth(oldRaster); - int oldHeight = RwRasterGetHeight(oldRaster); - if (oldWidth <= targetSize && oldHeight <= targetSize) return; + debug("Raster: %dx%d | depth: %d | format: 0x%X | stride: %d | platform: %d | pixels: %p", + r->width, + r->height, + r->depth, + r->format, + r->stride, + r->platform, + r->pixels); +} - int newWidth = clamp(oldWidth, targetSize); - int newHeight = clamp(oldHeight, targetSize); - if (newWidth == oldWidth && newHeight == oldHeight) return; +static void downscaleTexture(RwTexture *texture){ + #ifdef RW_GLES1 + if(texture == nil) + return; - RwImage *image = oldRaster->toImage(); - if (image == nil) return; + RwRaster *oldRaster = RwTextureGetRaster(texture); + if(oldRaster == nil) + return; - RwImage *resized = resizeImage(image, newWidth, newHeight); - RwImageDestroy(image); - if (resized == nil) return; + int oldWidth = RwRasterGetWidth(oldRaster); + int oldHeight = RwRasterGetHeight(oldRaster); - RwRaster *newRaster = rw::Raster::createFromImage(resized); - RwImageDestroy(resized); - if (newRaster == nil) return; + // dividir a la mitad, mínimo 16x16 + int newWidth = oldWidth > 16 ? oldWidth / 2 : oldWidth; + int newHeight = oldHeight > 16 ? oldHeight / 2 : oldHeight; - RwTextureSetRaster(texture, newRaster); - RwRasterDestroy(oldRaster); + // si ya es suficientemente chica, no hacer nada + if(newWidth == oldWidth && newHeight == oldHeight) + return; + + // toImage() funciona porque el backingStore está populado + RwImage *image = oldRaster->toImage(); + if(image == nil){ + debug("downscaleTexture: toImage FAILED for %dx%d", oldWidth, oldHeight); + return; + } + + RwImage *resized = resizeImage(image, newWidth, newHeight); + RwImageDestroy(image); + if(resized == nil){ + debug("downscaleTexture: resizeImage FAILED"); + return; + } + + // crear nuevo raster en formato compatible con GLES1 + int32 w, h, d, f; + rw::Raster::imageFindRasterFormat(resized, rw::Raster::TEXTURE, &w, &h, &d, &f); + RwRaster *newRaster = rw::Raster::create(w, h, d, f | rw::Raster::TEXTURE, rw::PLATFORM_GLES1); + if(newRaster == nil){ + debug("downscaleTexture: raster create FAILED"); + RwImageDestroy(resized); + return; + } + + if(newRaster->setFromImage(resized) == nil){ + debug("downscaleTexture: setFromImage FAILED"); + RwRasterDestroy(newRaster); + RwImageDestroy(resized); + return; + } + + RwImageDestroy(resized); + RwTextureSetRaster(texture, newRaster); + RwRasterDestroy(oldRaster); + #else + RwRaster *oldRaster = RwTextureGetRaster(texture); + if (oldRaster == nil) + return; + + extern bool moreVram; + int targetSize = moreVram ? 64 : 32; + + int oldWidth = RwRasterGetWidth(oldRaster); + int oldHeight = RwRasterGetHeight(oldRaster); + if (oldWidth <= targetSize && oldHeight <= targetSize) return; + + int newWidth = clamp(oldWidth, targetSize); + int newHeight = clamp(oldHeight, targetSize); + if (newWidth == oldWidth && newHeight == oldHeight) return; + + RwImage *image = oldRaster->toImage(); + if (image == nil) return; + + RwImage *resized = resizeImage(image, newWidth, newHeight); + RwImageDestroy(image); + if (resized == nil) return; + + RwRaster *newRaster = rw::Raster::createFromImage(resized); + RwImageDestroy(resized); + if (newRaster == nil) return; + + RwTextureSetRaster(texture, newRaster); + RwRasterDestroy(oldRaster); + #endif } #endif diff --git a/src/save/SaveBuf.h b/src/save/SaveBuf.h index aad2e1a..78ab6e4 100644 --- a/src/save/SaveBuf.h +++ b/src/save/SaveBuf.h @@ -70,4 +70,4 @@ ZeroSaveBuf(uint8 *&buf, uint32 length) } while(0) #else #define CheckSaveHeader(buf, a, b, c, d, size) SkipSaveBuf(buf, 8); -#endif \ No newline at end of file +#endif diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index a6ed8a7..8661f59 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -56,7 +56,7 @@ int _caserename(const char *old_filename, const char *new_filename); #define caserename _caserename #endif -#ifdef RW_GL3 +#if defined RW_GL3 || defined RW_GLES1 typedef struct { #ifndef __SYMBIAN32__ diff --git a/src/skel/symbian/symbian.cpp b/src/skel/symbian/symbian.cpp index d8db10b..78a839b 100644 --- a/src/skel/symbian/symbian.cpp +++ b/src/skel/symbian/symbian.cpp @@ -9,11 +9,19 @@ #include #include #include -#include +#ifdef RW_GL3 #include +#else +#include +#endif #include #include #include +#include +#include +#ifndef KFeatureIdQwertyInput +#include +#endif #include "common.h" #include "rwcore.h" @@ -79,10 +87,12 @@ static psGlobalType PsGlobal; static TBool foreground; -bool moreVram; - static bool spinning; +bool qwerty; +bool touch; +bool moreVram; + void _InputTranslateShiftKeyUpDown(RsKeyCodes *rs) { } @@ -292,22 +302,40 @@ static int MapScanCode(TInt aScanCode, TInt aModifiers) { return JOY_DPAD_RIGHT; } return JOY_DPAD_DOWN; + case 'z': case 'Z': + case '1': return JOY_B; case 'x': case 'X': + case '2': return JOY_X; - case 'c': - case 'C': + case 'a': + case 'A': + case '4': return JOY_A; + case 's': + case 'S': + case '3': + return JOY_Y; + + case '5': + return JOY_L1; + case '6': + return JOY_R1; + case '7': + return JOY_L2; + case '8': + return JOY_R2; + + case EStdKeyDevice0: + return JOY_BACK; + case EStdKeyDevice1: case EStdKeySpace: case ' ': return JOY_START; - case EStdKeyEnter: - case EStdKeyNkpEnter: - case EStdKeyDevice3: - return JOY_Y; + } return -1; } @@ -414,39 +442,54 @@ public: CreateWindowL(); iAppUi->SetOrientationL(CAknAppUiBase::EAppUiOrientationLandscape); SetExtentToWholeScreen(); + + SetFocus(ETrue); + +#ifdef RW_GL3 Window().EnableAdvancedPointers(); +#endif EnableDragEvents(); ActivateL(); - + +#ifdef RW_GL3 // VC4 check VersionInfo::TPlatformVersion platformVersion; VersionInfo::GetVersion(platformVersion); moreVram = platformVersion.iMajorVersion == 5 && platformVersion.iMinorVersion >= 4; +#endif TSize size = Size(); RsGlobal.width = size.iWidth; RsGlobal.height = size.iHeight; EGLint attribs[] = { - EGL_BUFFER_SIZE, 16, + EGL_BUFFER_SIZE, 24, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 0, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, +#ifdef RW_GL3 EGL_SAMPLES, 0, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#endif EGL_NONE }; eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(eglDisplay, NULL, NULL); +#ifdef RW_GL3 eglBindAPI(EGL_OPENGL_ES_API); +#endif EGLint numConfigs; eglChooseConfig(eglDisplay, attribs, &eglConfig, 1, &numConfigs); +#ifdef RW_GL3 EGLint contextAttribs[ 3 ] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs); +#else + eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, NULL); +#endif RWindow& window = Window(); eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, &window, NULL); @@ -458,6 +501,9 @@ public: setlocale(LC_COLLATE, "C"); setlocale(LC_NUMERIC, "C"); + touch = AknLayoutUtils::PenEnabled(); + TRAP_IGNORE(qwerty = CFeatureDiscovery::IsFeatureSupportedL(KFeatureIdQwertyInput)); + chdir("E:\\Data\\gta3\\"); gGameState = GS_START_UP; FrontEndMenuManager.LoadSettings(); @@ -471,7 +517,6 @@ public: openParams.width = RsGlobal.width; openParams.height = RsGlobal.height; - openParams.windowtitle = RsGlobal.appName; ControlsManager.MakeControllerActionsBlank(); ControlsManager.InitDefaultControlConfiguration(); @@ -523,9 +568,12 @@ public: // CCoeControl::HandlePointerEventL(aPointerEvent); // return; // } - +#ifdef RW_GL3 const TAdvancedPointerEvent* advpointer = aPointerEvent.AdvancedPointerEvent(); int i = advpointer != NULL ? advpointer->PointerNumber() : 0; +#else + int i = 0; +#endif static int activeZone[10]; static int stickCenterX[10]; diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index 157b485..a4547ea 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -78,4 +78,4 @@ VALIDATE_SIZE(CBoat, 0x484); extern float MAX_WAKE_LENGTH; extern float MIN_WAKE_INTERVAL; -extern float WAKE_LIFETIME; \ No newline at end of file +extern float WAKE_LIFETIME; diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index c7685e0..955cf6e 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -75,4 +75,4 @@ public: }; VALIDATE_SIZE(CWeapon, 0x18); -void FireOneInstantHitRound(CVector *source, CVector *target, int32 damage); \ No newline at end of file +void FireOneInstantHitRound(CVector *source, CVector *target, int32 damage); diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h index 96e2ecf..819de50 100644 --- a/src/weapons/WeaponInfo.h +++ b/src/weapons/WeaponInfo.h @@ -49,4 +49,4 @@ public: bool IsFlagSet(uint32 flag) const { return (m_Flags & flag) != 0; } }; -VALIDATE_SIZE(CWeaponInfo, 0x54); \ No newline at end of file +VALIDATE_SIZE(CWeaponInfo, 0x54); diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h index b45740b..9878281 100644 --- a/src/weapons/WeaponType.h +++ b/src/weapons/WeaponType.h @@ -46,4 +46,4 @@ enum eWeaponState WEAPONSTATE_RELOADING, WEAPONSTATE_OUT_OF_AMMO, WEAPONSTATE_MELEE_MADECONTACT -}; \ No newline at end of file +}; diff --git a/vendor/librw/rw.h b/vendor/librw/rw.h index c6a36ce..f1a29c1 100644 --- a/vendor/librw/rw.h +++ b/vendor/librw/rw.h @@ -25,3 +25,4 @@ #include "src/gl/rwgl3.h" #include "src/gl/rwgl3shader.h" #include "src/gl/rwgl3plg.h" +#include "src/gles1/rwgles1.h" diff --git a/vendor/librw/src/base.cpp b/vendor/librw/src/base.cpp index 24472ea..e3b78a0 100644 --- a/vendor/librw/src/base.cpp +++ b/vendor/librw/src/base.cpp @@ -26,13 +26,15 @@ namespace rw { int32 version = 0x36003; int32 build = 0xFFFF; -#ifdef RW_PS2 +#if defined RW_PS2 int32 platform = PLATFORM_PS2; -#elif RW_WDGL +#elif defined RW_WDGL int32 platform = PLATFORM_WDGL; -#elif RW_GL3 +#elif defined RW_GL3 int32 platform = PLATFORM_GL3; -#elif RW_D3D9 +#elif defined RW_GLES1 + int32 platform = PLATFORM_GLES1; +#elif defined RW_D3D9 int32 platform = PLATFORM_D3D9; #else int32 platform = PLATFORM_NULL; diff --git a/vendor/librw/src/charset.cpp b/vendor/librw/src/charset.cpp index 5188b80..d1e50c8 100644 --- a/vendor/librw/src/charset.cpp +++ b/vendor/librw/src/charset.cpp @@ -12,6 +12,7 @@ #include "ps2/rwps2.h" #include "d3d/rwd3d.h" #include "gl/rwgl3.h" +#include "gles1/rwgles1.h" #define PLUGIN_ID 1000 // TODO: find a better ID diff --git a/vendor/librw/src/d3d/d3d9.cpp b/vendor/librw/src/d3d/d3d9.cpp index 851397b..bd79266 100644 --- a/vendor/librw/src/d3d/d3d9.cpp +++ b/vendor/librw/src/d3d/d3d9.cpp @@ -554,7 +554,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) // We expect some attributes to always be there, use the constant buffer as fallback if(!isPrelit){ dcl[i].stream = 2; - dcl[i].offset = offsetof(VertexConstantData, color); + dcl[i].offset = OFFSET_OF(VertexConstantData, color); dcl[i].type = D3DDECLTYPE_D3DCOLOR; dcl[i].method = D3DDECLMETHOD_DEFAULT; dcl[i].usage = D3DDECLUSAGE_COLOR; @@ -563,7 +563,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) } if(geo->numTexCoordSets == 0){ dcl[i].stream = 2; - dcl[i].offset = offsetof(VertexConstantData, texCoors[0]); + dcl[i].offset = OFFSET_OF(VertexConstantData, texCoors); dcl[i].type = D3DDECLTYPE_FLOAT2; dcl[i].method = D3DDECLMETHOD_DEFAULT; dcl[i].usage = D3DDECLUSAGE_TEXCOORD; diff --git a/vendor/librw/src/engine.cpp b/vendor/librw/src/engine.cpp index 327c8bf..d3ce4e3 100644 --- a/vendor/librw/src/engine.cpp +++ b/vendor/librw/src/engine.cpp @@ -17,6 +17,7 @@ #include "d3d/rwd3d9.h" #include "gl/rwgl3.h" #include "gl/rwwdgl.h" +#include "gles1/rwgles1.h" #define PLUGIN_ID 0 @@ -243,6 +244,9 @@ Engine::init(MemoryFunctions *memfuncs) d3d9::registerPlatformPlugins(); wdgl::registerPlatformPlugins(); gl3::registerPlatformPlugins(); +#ifdef RW_GLES1 + gles1::registerPlatformPlugins(); +#endif Engine::state = Initialized; return 1; @@ -264,11 +268,13 @@ Engine::open(EngineOpenParams *p) // Initialize device // Device and possibly OS specific! -#ifdef RW_PS2 +#if defined RW_PS2 engine->device = ps2::renderdevice; -#elif RW_GL3 +#elif defined RW_GL3 engine->device = gl3::renderdevice; -#elif RW_D3D9 +#elif defined RW_GLES1 + engine->device = gles1::renderdevice; +#elif defined RW_D3D9 engine->device = d3d::renderdevice; #else engine->device = null::renderdevice; diff --git a/vendor/librw/src/geoplg.cpp b/vendor/librw/src/geoplg.cpp index c1e1356..fa8ba4b 100644 --- a/vendor/librw/src/geoplg.cpp +++ b/vendor/librw/src/geoplg.cpp @@ -18,6 +18,7 @@ #include "d3d/rwd3d9.h" #include "gl/rwwdgl.h" #include "gl/rwgl3.h" +#include "gles1/rwgles1.h" #define PLUGIN_ID 2 @@ -251,6 +252,10 @@ destroyNativeData(void *object, int32 offset, int32 size) return d3d9::destroyNativeData(object, offset, size); if(geometry->instData->platform == PLATFORM_GL3) return gl3::destroyNativeData(object, offset, size); +#ifdef RW_GLES1 + if(geometry->instData->platform == PLATFORM_GLES1) + return gles1::destroyNativeData(object, offset, size); +#endif return object; } diff --git a/vendor/librw/src/gl/gl3device.cpp b/vendor/librw/src/gl/gl3device.cpp index 68c72c4..5f7f5a4 100644 --- a/vendor/librw/src/gl/gl3device.cpp +++ b/vendor/librw/src/gl/gl3device.cpp @@ -1565,7 +1565,6 @@ openSymbian(EngineOpenParams *openparams) { glGlobals.winWidth = openparams->width; glGlobals.winHeight = openparams->height; - glGlobals.winTitle = openparams->windowtitle; glGlobals.modes = (DisplayMode*)rwMalloc(sizeof(DisplayMode), ID_DRIVER | MEMDUR_EVENT); glGlobals.modes[0].width = openparams->width; diff --git a/vendor/librw/src/gl/wdgl.cpp b/vendor/librw/src/gl/wdgl.cpp index 6474d2b..ee730fe 100644 --- a/vendor/librw/src/gl/wdgl.cpp +++ b/vendor/librw/src/gl/wdgl.cpp @@ -14,9 +14,13 @@ #include "rwwdgl.h" #ifdef __SYMBIAN32__ +#ifdef RW_GL3 #include #include #else +#include +#endif +#else #ifdef RW_OPENGL #include "glad/glad.h" #endif diff --git a/vendor/librw/src/gles1/gl1.cpp b/vendor/librw/src/gles1/gl1.cpp new file mode 100644 index 0000000..b185063 --- /dev/null +++ b/vendor/librw/src/gles1/gl1.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" + +#include "rwgles1.h" +#include "rwgles1impl.h" + +#ifdef RW_GLES1 + +namespace rw { +namespace gles1 { + +static void* +driverOpen(void* object, int32 offset, int32 size) +{ + engine->driver[PLATFORM_GLES1]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_GLES1]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_GLES1]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_GLES1]->rasterLock = rasterLock; + engine->driver[PLATFORM_GLES1]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_GLES1]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_GLES1]->imageFindRasterFormat = imageFindRasterFormat; + engine->driver[PLATFORM_GLES1]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_GLES1]->rasterToImage = rasterToImage; + return object; +} + +static void* +driverClose(void* object, int32 offset, int32 size) +{ + // stub: no hace nada + return object; +} + +void +registerPlatformPlugins(void) +{ + Driver::registerPlugin(PLATFORM_GLES1, 0, PLATFORM_GLES1, + driverOpen, driverClose); + registerNativeRaster(); +} + +} +} + +#endif diff --git a/vendor/librw/src/gles1/gl1device.cpp b/vendor/librw/src/gles1/gl1device.cpp new file mode 100644 index 0000000..790dd5d --- /dev/null +++ b/vendor/librw/src/gles1/gl1device.cpp @@ -0,0 +1,1500 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwrender.h" +#include "../rwengine.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#ifdef RW_GLES1 + +#include "rwgles1.h" +#include "rwgles1impl.h" + +#define PLUGIN_ID 0 + +namespace rw { +namespace gles1 { + +GlGlobals glGlobals; + +// terrible hack for GLES +bool32 needToReadBackTextures; + +float32 alphaRef; + +struct UniformState +{ + float32 fogStart; + float32 fogEnd; + RGBAf fogColor; +}; + +struct UniformScene +{ + float32 proj[16]; + float32 view[16]; +}; + +#define MAX_LIGHTS 8 + +struct UniformObject +{ + RawMatrix world; + RGBAf ambLight; + struct { + float type; + float radius; + float minusCosAngle; + float hardSpot; + } lightParams[MAX_LIGHTS]; + V4d lightPosition[MAX_LIGHTS]; + V4d lightDirection[MAX_LIGHTS]; + RGBAf lightColor[MAX_LIGHTS]; +}; + + + +static GLuint vao; +static GLuint whitetex; +static UniformState uniformState; +static UniformScene uniformScene; +static UniformObject uniformObject; + +int32 u_matColor; +int32 u_surfProps; + +static bool32 stateDirty = 1; +static bool32 sceneDirty = 1; +static bool32 objectDirty = 1; + +struct RwRasterStateCache { + Raster *raster; + Texture::Addressing addressingU; + Texture::Addressing addressingV; + Texture::FilterMode filter; +}; + +#define MAXNUMSTAGES 8 + +// cached RW render states +struct RwStateCache { + bool32 vertexAlpha; + uint32 alphaTestEnable; + uint32 alphaFunc; + bool32 textureAlpha; + bool32 blendEnable; + uint32 srcblend, destblend; + uint32 zwrite; + uint32 ztest; + uint32 cullmode; + uint32 stencilenable; + uint32 stencilpass; + uint32 stencilfail; + uint32 stencilzfail; + uint32 stencilfunc; + uint32 stencilref; + uint32 stencilmask; + uint32 stencilwritemask; + uint32 fogEnable; + float32 fogStart; + float32 fogEnd; + + // emulation of PS2 GS + bool32 gsalpha; + uint32 gsalpharef; + + RwRasterStateCache texstage[MAXNUMSTAGES]; +}; +static RwStateCache rwStateCache; + +enum +{ + // actual gl states + RWGL_BLEND, + RWGL_SRCBLEND, + RWGL_DESTBLEND, + RWGL_DEPTHTEST, + RWGL_DEPTHFUNC, + RWGL_DEPTHMASK, + RWGL_CULL, + RWGL_CULLFACE, + RWGL_STENCIL, + RWGL_STENCILFUNC, + RWGL_STENCILFAIL, + RWGL_STENCILZFAIL, + RWGL_STENCILPASS, + RWGL_STENCILREF, + RWGL_STENCILMASK, + RWGL_STENCILWRITEMASK, + + // uniforms + RWGL_ALPHAFUNC, + RWGL_ALPHAREF, + RWGL_FOG, + RWGL_FOGSTART, + RWGL_FOGEND, + RWGL_FOGCOLOR, + + RWGL_NUM_STATES +}; +static bool uniformStateDirty[RWGL_NUM_STATES]; + +struct GlState { + bool32 blendEnable; + uint32 srcblend, destblend; + + bool32 depthTest; + uint32 depthFunc; + + uint32 depthMask; + + bool32 cullEnable; + uint32 cullFace; + + bool32 stencilEnable; + // glStencilFunc + uint32 stencilFunc; + uint32 stencilRef; + uint32 stencilMask; + // glStencilOp + uint32 stencilPass; + uint32 stencilFail; + uint32 stencilZFail; + // glStencilMask + uint32 stencilWriteMask; +}; +static GlState curGlState, oldGlState; + +static int32 activeTexture; +static uint32 boundTexture[MAXNUMSTAGES]; + +static uint32 currentFramebuffer; + +static uint32 blendMap[] = { + GL_ZERO, // actually invalid + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA_SATURATE, +}; + +static uint32 stencilOpMap[] = { + GL_KEEP, // actually invalid + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR, + GL_DECR, + GL_INVERT, + GL_INCR,//_WRAP, + GL_DECR//_WRAP +}; + +static uint32 stencilFuncMap[] = { + GL_NEVER, // actually invalid + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS +}; + +static float maxAnisotropy; + +/* + * GL state cache + */ + +void +setGlRenderState(uint32 state, uint32 value) +{ + switch(state){ + case RWGL_BLEND: curGlState.blendEnable = value; break; + case RWGL_SRCBLEND: curGlState.srcblend = value; break; + case RWGL_DESTBLEND: curGlState.destblend = value; break; + case RWGL_DEPTHTEST: curGlState.depthTest = value; break; + case RWGL_DEPTHFUNC: curGlState.depthFunc = value; break; + case RWGL_DEPTHMASK: curGlState.depthMask = value; break; + case RWGL_CULL: curGlState.cullEnable = value; break; + case RWGL_CULLFACE: curGlState.cullFace = value; break; + case RWGL_STENCIL: curGlState.stencilEnable = value; break; + case RWGL_STENCILFUNC: curGlState.stencilFunc = value; break; + case RWGL_STENCILFAIL: curGlState.stencilFail = value; break; + case RWGL_STENCILZFAIL: curGlState.stencilZFail = value; break; + case RWGL_STENCILPASS: curGlState.stencilPass = value; break; + case RWGL_STENCILREF: curGlState.stencilRef = value; break; + case RWGL_STENCILMASK: curGlState.stencilMask = value; break; + case RWGL_STENCILWRITEMASK: curGlState.stencilWriteMask = value; break; + } +} + +void +flushGlRenderState(void) +{ + if(oldGlState.blendEnable != curGlState.blendEnable){ + oldGlState.blendEnable = curGlState.blendEnable; + (oldGlState.blendEnable ? glEnable : glDisable)(GL_BLEND); + } + + if(oldGlState.srcblend != curGlState.srcblend || + oldGlState.destblend != curGlState.destblend){ + oldGlState.srcblend = curGlState.srcblend; + oldGlState.destblend = curGlState.destblend; + glBlendFunc(oldGlState.srcblend, oldGlState.destblend); + } + + if(oldGlState.depthTest != curGlState.depthTest){ + oldGlState.depthTest = curGlState.depthTest; + (oldGlState.depthTest ? glEnable : glDisable)(GL_DEPTH_TEST); + } + if(oldGlState.depthFunc != curGlState.depthFunc){ + oldGlState.depthFunc = curGlState.depthFunc; + glDepthFunc(oldGlState.depthFunc); + } + if(oldGlState.depthMask != curGlState.depthMask){ + oldGlState.depthMask = curGlState.depthMask; + glDepthMask(oldGlState.depthMask); + } + + if(oldGlState.stencilEnable != curGlState.stencilEnable){ + oldGlState.stencilEnable = curGlState.stencilEnable; + (oldGlState.stencilEnable ? glEnable : glDisable)(GL_STENCIL_TEST); + } + if(oldGlState.stencilFunc != curGlState.stencilFunc || + oldGlState.stencilRef != curGlState.stencilRef || + oldGlState.stencilMask != curGlState.stencilMask){ + oldGlState.stencilFunc = curGlState.stencilFunc; + oldGlState.stencilRef = curGlState.stencilRef; + oldGlState.stencilMask = curGlState.stencilMask; + glStencilFunc(oldGlState.stencilFunc, oldGlState.stencilRef, oldGlState.stencilMask); + } + if(oldGlState.stencilPass != curGlState.stencilPass || + oldGlState.stencilFail != curGlState.stencilFail || + oldGlState.stencilZFail != curGlState.stencilZFail){ + oldGlState.stencilPass = curGlState.stencilPass; + oldGlState.stencilFail = curGlState.stencilFail; + oldGlState.stencilZFail = curGlState.stencilZFail; + glStencilOp(oldGlState.stencilFail, oldGlState.stencilZFail, oldGlState.stencilPass); + } + if(oldGlState.stencilWriteMask != curGlState.stencilWriteMask){ + oldGlState.stencilWriteMask = curGlState.stencilWriteMask; + glStencilMask(oldGlState.stencilWriteMask); + } + + if(oldGlState.cullEnable != curGlState.cullEnable){ + oldGlState.cullEnable = curGlState.cullEnable; + (oldGlState.cullEnable ? glEnable : glDisable)(GL_CULL_FACE); + } + if(oldGlState.cullFace != curGlState.cullFace){ + oldGlState.cullFace = curGlState.cullFace; + glCullFace(oldGlState.cullFace); + } +} + + + +void setAlphaBlend(bool32 enable){ + if(rwStateCache.blendEnable != enable){ + rwStateCache.blendEnable = enable; + setGlRenderState(RWGL_BLEND, enable); + } +} + +bool32 +getAlphaBlend(void) +{ + return rwStateCache.blendEnable; +} + +bool32 getAlphaTest(void) { return rwStateCache.alphaTestEnable; } + +static void +setDepthTest(bool32 enable) +{ + if(rwStateCache.ztest != enable){ + rwStateCache.ztest = enable; + if(rwStateCache.zwrite && !enable){ + // If we still want to write, enable but set mode to always + setGlRenderState(RWGL_DEPTHTEST, true); + setGlRenderState(RWGL_DEPTHFUNC, GL_ALWAYS); + }else{ + setGlRenderState(RWGL_DEPTHTEST, rwStateCache.ztest); + setGlRenderState(RWGL_DEPTHFUNC, GL_LEQUAL); + } + } +} + +static void +setDepthWrite(bool32 enable) +{ + enable = enable ? GL_TRUE : GL_FALSE; + if(rwStateCache.zwrite != enable){ + rwStateCache.zwrite = enable; + if(enable && !rwStateCache.ztest){ + // Have to switch on ztest so writing can work + setGlRenderState(RWGL_DEPTHTEST, true); + setGlRenderState(RWGL_DEPTHFUNC, GL_ALWAYS); + } + setGlRenderState(RWGL_DEPTHMASK, rwStateCache.zwrite); + } +} + +static void setAlphaTest(bool32 enable) +{ + if(rwStateCache.alphaTestEnable != enable){ + rwStateCache.alphaTestEnable = enable; + uniformStateDirty[RWGL_ALPHAFUNC] = true; + stateDirty = 1; + } +} + +static void setAlphaTestFunction(uint32 function) +{ + if(rwStateCache.alphaFunc != function){ + rwStateCache.alphaFunc = function; + uniformStateDirty[RWGL_ALPHAFUNC] = true; + stateDirty = 1; + } +} + +void setVertexAlpha(bool32 enable) +{ + if(rwStateCache.vertexAlpha != enable){ + if(!rwStateCache.textureAlpha){ + setAlphaBlend(enable); + setAlphaTest(enable); + } + rwStateCache.vertexAlpha = enable; + } +} + +static void +setActiveTexture(int32 n) +{ + if(activeTexture != n){ + activeTexture = n; + glActiveTexture(GL_TEXTURE0+n); + } +} + +uint32 +bindTexture(uint32 texid) +{ + uint32 prev = boundTexture[activeTexture]; + if(prev != texid){ + boundTexture[activeTexture] = texid; + glBindTexture(GL_TEXTURE_2D, texid); + } + return prev; +} + +void +bindFramebuffer(uint32 fbo) +{ + if(currentFramebuffer != fbo){ +// glBindFramebuffer(GL_FRAMEBUFFER, fbo); + currentFramebuffer = fbo; + } +} + +static GLint filterConvMap_NoMIP[] = { + 0, GL_NEAREST, GL_LINEAR, + GL_NEAREST, GL_LINEAR, + GL_NEAREST, GL_LINEAR +}; +static GLint filterConvMap_MIP[] = { + 0, GL_NEAREST, GL_LINEAR, + GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, + GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR +}; + +static GLint addressConvMap[] = { + 0, GL_REPEAT, GL_REPEAT, //GL_MIRRORED_REPEAT, +#ifdef __SYMBIAN32__ + // TODO + GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE +#else + GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER +#endif +}; + +static void +setFilterMode(uint32 stage, int32 filter, int32 maxAniso = 1) +{ + if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){ + rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter; + Raster *raster = rwStateCache.texstage[stage].raster; + if(raster){ + Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, rwStateCache.texstage[stage].raster, nativeRasterOffset); + if(natras->filterMode != filter){ + setActiveTexture(stage); +// if(natras->autogenMipmap || natras->numLevels > 1){ +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_MIP[filter]); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]); +// }else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]); + } + natras->filterMode = filter; + } + if(natras->maxAnisotropy != maxAniso){ + setActiveTexture(stage); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)maxAniso); + natras->maxAnisotropy = maxAniso; + } + } + } +} + +static void +setAddressU(uint32 stage, int32 addressing) +{ + if(rwStateCache.texstage[stage].addressingU != (Texture::Addressing)addressing){ + rwStateCache.texstage[stage].addressingU = (Texture::Addressing)addressing; + Raster *raster = rwStateCache.texstage[stage].raster; + if(raster){ + Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, raster, nativeRasterOffset); + if(natras->addressU == addressing){ + setActiveTexture(stage); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, addressConvMap[addressing]); + natras->addressU = addressing; + } + } + } +} + +static void +setAddressV(uint32 stage, int32 addressing) +{ + if(rwStateCache.texstage[stage].addressingV != (Texture::Addressing)addressing){ + rwStateCache.texstage[stage].addressingV = (Texture::Addressing)addressing; + Raster *raster = rwStateCache.texstage[stage].raster; + if(raster){ + Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, rwStateCache.texstage[stage].raster, nativeRasterOffset); + if(natras->addressV == addressing){ + setActiveTexture(stage); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, addressConvMap[addressing]); + natras->addressV = addressing; + } + } + } +} + +static void +setRasterStageOnly(uint32 stage, Raster *raster) +{ + bool32 alpha; + if(raster != rwStateCache.texstage[stage].raster){ + rwStateCache.texstage[stage].raster = raster; + setActiveTexture(stage); + if(raster){ + assert(raster->platform == PLATFORM_GLES1); + Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, raster, nativeRasterOffset); + glEnable(GL_TEXTURE_2D); + bindTexture(natras->texid); + + rwStateCache.texstage[stage].filter = (rw::Texture::FilterMode)natras->filterMode; + rwStateCache.texstage[stage].addressingU = (rw::Texture::Addressing)natras->addressU; + rwStateCache.texstage[stage].addressingV = (rw::Texture::Addressing)natras->addressV; + + alpha = natras->hasAlpha; + }else{ + glDisable(GL_TEXTURE_2D); + bindTexture(whitetex); + alpha = 0; + } + + if(stage == 0){ + if(alpha != rwStateCache.textureAlpha){ + rwStateCache.textureAlpha = alpha; + if(!rwStateCache.vertexAlpha){ + setAlphaBlend(alpha); + setAlphaTest(alpha); + } + } + } + } +} + +static void +setRasterStage(uint32 stage, Raster *raster) +{ + bool32 alpha; + if(raster != rwStateCache.texstage[stage].raster){ + rwStateCache.texstage[stage].raster = raster; + setActiveTexture(stage); + if(raster){ + assert(raster->platform == PLATFORM_GLES1); + Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, raster, nativeRasterOffset); + glEnable(GL_TEXTURE_2D); + bindTexture(natras->texid); + uint32 filter = rwStateCache.texstage[stage].filter; + uint32 addrU = rwStateCache.texstage[stage].addressingU; + uint32 addrV = rwStateCache.texstage[stage].addressingV; + if(natras->filterMode != filter){ +// if(natras->autogenMipmap || natras->numLevels > 1){ +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_MIP[filter]); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]); +// }else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]); + } + natras->filterMode = filter; + } + if(natras->addressU != addrU){ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, addressConvMap[addrU]); + natras->addressU = addrU; + } + if(natras->addressV != addrV){ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, addressConvMap[addrV]); + natras->addressV = addrV; + } + alpha = natras->hasAlpha; + }else{ + glDisable(GL_TEXTURE_2D); + bindTexture(whitetex); + alpha = 0; + } + + if(stage == 0){ + if(alpha != rwStateCache.textureAlpha){ + rwStateCache.textureAlpha = alpha; + if(!rwStateCache.vertexAlpha){ + setAlphaBlend(alpha); + setAlphaTest(alpha); + } + } + } + } +} + +void +evictRaster(Raster *raster) +{ + int i; + for(i = 0; i < MAXNUMSTAGES; i++){ + //assert(rwStateCache.texstage[i].raster != raster); + if(rwStateCache.texstage[i].raster != raster) + continue; + setRasterStage(i, nil); + } +} + +void +setTexture(int32 stage, Texture *tex) +{ + if(tex == nil || tex->raster == nil){ + setRasterStage(stage, nil); + return; + } + setRasterStageOnly(stage, tex->raster); + setFilterMode(stage, tex->getFilter(), tex->getMaxAnisotropy()); + setAddressU(stage, tex->getAddressU()); + setAddressV(stage, tex->getAddressV()); +} + +static void +setRenderState(int32 state, void *pvalue) +{ + uint32 value = (uint32)(uintptr)pvalue; + switch(state){ + case TEXTURERASTER: + setRasterStage(0, (Raster*)pvalue); + break; + case TEXTUREADDRESS: + setAddressU(0, value); + setAddressV(0, value); + break; + case TEXTUREADDRESSU: + setAddressU(0, value); + break; + case TEXTUREADDRESSV: + setAddressV(0, value); + break; + case TEXTUREFILTER: + setFilterMode(0, value); + break; + case VERTEXALPHA: + setVertexAlpha(value); + break; + case SRCBLEND: + if(rwStateCache.srcblend != value){ + rwStateCache.srcblend = value; + setGlRenderState(RWGL_SRCBLEND, blendMap[rwStateCache.srcblend]); + } + break; + case DESTBLEND: + if(rwStateCache.destblend != value){ + rwStateCache.destblend = value; + setGlRenderState(RWGL_DESTBLEND, blendMap[rwStateCache.destblend]); + } + break; + case ZTESTENABLE: + setDepthTest(value); + break; + case ZWRITEENABLE: + setDepthWrite(value); + break; + case FOGENABLE: + if(rwStateCache.fogEnable != value){ + rwStateCache.fogEnable = value; + uniformStateDirty[RWGL_FOG] = true; + stateDirty = 1; + } + break; + case FOGCOLOR: + // no cache check here...too lazy + RGBA c; + c.red = value; + c.green = value>>8; + c.blue = value>>16; + c.alpha = value>>24; + convColor(&uniformState.fogColor, &c); + uniformStateDirty[RWGL_FOGCOLOR] = true; + stateDirty = 1; + break; + case CULLMODE: + if(rwStateCache.cullmode != value){ + rwStateCache.cullmode = value; + if(rwStateCache.cullmode == CULLNONE) + setGlRenderState(RWGL_CULL, false); + else{ + setGlRenderState(RWGL_CULL, true); + setGlRenderState(RWGL_CULLFACE, rwStateCache.cullmode == CULLBACK ? GL_BACK : GL_FRONT); + } + } + break; + + case STENCILENABLE: + if(rwStateCache.stencilenable != value){ + rwStateCache.stencilenable = value; + setGlRenderState(RWGL_STENCIL, value); + } + break; + case STENCILFAIL: + if(rwStateCache.stencilfail != value){ + rwStateCache.stencilfail = value; + setGlRenderState(RWGL_STENCILFAIL, stencilOpMap[value]); + } + break; + case STENCILZFAIL: + if(rwStateCache.stencilzfail != value){ + rwStateCache.stencilzfail = value; + setGlRenderState(RWGL_STENCILZFAIL, stencilOpMap[value]); + } + break; + case STENCILPASS: + if(rwStateCache.stencilpass != value){ + rwStateCache.stencilpass = value; + setGlRenderState(RWGL_STENCILPASS, stencilOpMap[value]); + } + break; + case STENCILFUNCTION: + if(rwStateCache.stencilfunc != value){ + rwStateCache.stencilfunc = value; + setGlRenderState(RWGL_STENCILFUNC, stencilFuncMap[value]); + } + break; + case STENCILFUNCTIONREF: + if(rwStateCache.stencilref != value){ + rwStateCache.stencilref = value; + setGlRenderState(RWGL_STENCILREF, value); + } + break; + case STENCILFUNCTIONMASK: + if(rwStateCache.stencilmask != value){ + rwStateCache.stencilmask = value; + setGlRenderState(RWGL_STENCILMASK, value); + } + break; + case STENCILFUNCTIONWRITEMASK: + if(rwStateCache.stencilwritemask != value){ + rwStateCache.stencilwritemask = value; + setGlRenderState(RWGL_STENCILWRITEMASK, value); + } + break; + + case ALPHATESTFUNC: + setAlphaTestFunction(value); + break; + case ALPHATESTREF: + if(alphaRef != value/255.0f){ + alphaRef = value/255.0f; + uniformStateDirty[RWGL_ALPHAREF] = true; + stateDirty = 1; + } + break; + case GSALPHATEST: + rwStateCache.gsalpha = value; + break; + case GSALPHATESTREF: + rwStateCache.gsalpharef = value; + } +} + +static void* +getRenderState(int32 state) +{ + uint32 val; + RGBA rgba; + switch(state){ + case TEXTURERASTER: + return rwStateCache.texstage[0].raster; + case TEXTUREADDRESS: + if(rwStateCache.texstage[0].addressingU == rwStateCache.texstage[0].addressingV) + val = rwStateCache.texstage[0].addressingU; + else + val = 0; // invalid + break; + case TEXTUREADDRESSU: + val = rwStateCache.texstage[0].addressingU; + break; + case TEXTUREADDRESSV: + val = rwStateCache.texstage[0].addressingV; + break; + case TEXTUREFILTER: + val = rwStateCache.texstage[0].filter; + break; + + case VERTEXALPHA: + val = rwStateCache.vertexAlpha; + break; + case SRCBLEND: + val = rwStateCache.srcblend; + break; + case DESTBLEND: + val = rwStateCache.destblend; + break; + case ZTESTENABLE: + val = rwStateCache.ztest; + break; + case ZWRITEENABLE: + val = rwStateCache.zwrite; + break; + case FOGENABLE: + val = rwStateCache.fogEnable; + break; + case FOGCOLOR: + convColor(&rgba, &uniformState.fogColor); + val = RWRGBAINT(rgba.red, rgba.green, rgba.blue, rgba.alpha); + break; + case CULLMODE: + val = rwStateCache.cullmode; + break; + + case STENCILENABLE: + val = rwStateCache.stencilenable; + break; + case STENCILFAIL: + val = rwStateCache.stencilfail; + break; + case STENCILZFAIL: + val = rwStateCache.stencilzfail; + break; + case STENCILPASS: + val = rwStateCache.stencilpass; + break; + case STENCILFUNCTION: + val = rwStateCache.stencilfunc; + break; + case STENCILFUNCTIONREF: + val = rwStateCache.stencilref; + break; + case STENCILFUNCTIONMASK: + val = rwStateCache.stencilmask; + break; + case STENCILFUNCTIONWRITEMASK: + val = rwStateCache.stencilwritemask; + break; + + case ALPHATESTFUNC: + val = rwStateCache.alphaFunc; + break; + case ALPHATESTREF: + val = (uint32)(alphaRef*255.0f); + break; + case GSALPHATEST: + val = rwStateCache.gsalpha; + break; + case GSALPHATESTREF: + val = rwStateCache.gsalpharef; + break; + default: + val = 0; + } + return (void*)(uintptr)val; +} + +static void +resetRenderState(void) +{ + rwStateCache.alphaFunc = ALPHAGREATEREQUAL; + alphaRef = 10.0f/255.0f; + uniformState.fogStart = 0.0f; + uniformState.fogEnd = 0.0f; + uniformState.fogColor.red = 1.0f; + uniformState.fogColor.green = 1.0f; + uniformState.fogColor.blue = 1.0f; + uniformState.fogColor.alpha = 1.0f; + rwStateCache.gsalpha = 0; + rwStateCache.gsalpharef = 128; + stateDirty = 1; + + rwStateCache.vertexAlpha = 0; + rwStateCache.textureAlpha = 0; + rwStateCache.alphaTestEnable = 0; + + memset(&oldGlState, 0xFE, sizeof(oldGlState)); + + rwStateCache.blendEnable = 0; + setGlRenderState(RWGL_BLEND, false); + rwStateCache.srcblend = BLENDSRCALPHA; + rwStateCache.destblend = BLENDINVSRCALPHA; + setGlRenderState(RWGL_SRCBLEND, blendMap[rwStateCache.srcblend]); + setGlRenderState(RWGL_DESTBLEND, blendMap[rwStateCache.destblend]); + + rwStateCache.zwrite = GL_TRUE; + setGlRenderState(RWGL_DEPTHMASK, rwStateCache.zwrite); + + rwStateCache.ztest = 1; + setGlRenderState(RWGL_DEPTHTEST, true); + setGlRenderState(RWGL_DEPTHFUNC, GL_LEQUAL); + + rwStateCache.cullmode = CULLNONE; + setGlRenderState(RWGL_CULL, false); + setGlRenderState(RWGL_CULLFACE, GL_BACK); + + rwStateCache.stencilenable = 0; + setGlRenderState(RWGL_STENCIL, GL_FALSE); + rwStateCache.stencilfail = STENCILKEEP; + setGlRenderState(RWGL_STENCILFAIL, GL_KEEP); + rwStateCache.stencilzfail = STENCILKEEP; + setGlRenderState(RWGL_STENCILZFAIL, GL_KEEP); + rwStateCache.stencilpass = STENCILKEEP; + setGlRenderState(RWGL_STENCILPASS, GL_KEEP); + rwStateCache.stencilfunc = STENCILALWAYS; + setGlRenderState(RWGL_STENCILFUNC, GL_ALWAYS); + rwStateCache.stencilref = 0; + setGlRenderState(RWGL_STENCILREF, 0); + rwStateCache.stencilmask = 0xFFFFFFFF; + setGlRenderState(RWGL_STENCILMASK, 0xFFFFFFFF); + rwStateCache.stencilwritemask = 0xFFFFFFFF; + setGlRenderState(RWGL_STENCILWRITEMASK, 0xFFFFFFFF); + + activeTexture = -1; + for(int i = 0; i < MAXNUMSTAGES; i++){ + setActiveTexture(i); + bindTexture(whitetex); + glDisable(GL_TEXTURE_2D); + } + setActiveTexture(0); + + glDisable(GL_LIGHTING); + glDisable(GL_FOG); + glDisable(GL_ALPHA_TEST); +} + +void +setWorldMatrix(Matrix *mat) +{ + convMatrix(&uniformObject.world, mat); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(uniformScene.view); + glMultMatrixf((float*)&uniformObject.world); + objectDirty = 1; +} + +int32 +setLights(WorldLights *lightData) +{ + //sin luces. menos codigo + glDisable(GL_LIGHTING); + return 0; + + /*int i, n; + Light *l; + int32 bits = 0; + + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (GLfloat*)&lightData->ambient); + + if(lightData->numAmbients) + bits |= VSLIGHT_AMBIENT; + + n = 0; + for(i = 0; i < MAX_LIGHTS; i++) + glDisable(GL_LIGHT0 + i); + + for(i = 0; i < lightData->numDirectionals && i < 8; i++){ + l = lightData->directionals[i]; + glEnable(GL_LIGHT0 + n); + GLfloat dir[4] = { -l->getFrame()->getLTM()->at.x, -l->getFrame()->getLTM()->at.y, -l->getFrame()->getLTM()->at.z, 0.0f }; + glLightfv(GL_LIGHT0 + n, GL_POSITION, dir); + glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, (GLfloat*)&l->color); + glLightfv(GL_LIGHT0 + n, GL_SPECULAR, (GLfloat*)&l->color); + bits |= VSLIGHT_DIRECT; + n++; + if(n >= MAX_LIGHTS) goto out; + } + + for(i = 0; i < lightData->numLocals; i++){ + Light *l = lightData->locals[i]; + + switch(l->getType()){ + case Light::POINT: + glEnable(GL_LIGHT0 + n); + { + GLfloat pos[4] = { l->getFrame()->getLTM()->pos.x, l->getFrame()->getLTM()->pos.y, l->getFrame()->getLTM()->pos.z, 1.0f }; + glLightfv(GL_LIGHT0 + n, GL_POSITION, pos); + glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, (GLfloat*)&l->color); + glLightf(GL_LIGHT0 + n, GL_CONSTANT_ATTENUATION, 1.0f); + glLightf(GL_LIGHT0 + n, GL_LINEAR_ATTENUATION, l->radius > 0.0f ? 1.0f / l->radius : 0.0f); + } + bits |= VSLIGHT_POINT; + n++; + if(n >= MAX_LIGHTS) goto out; + break; + case Light::SPOT: + case Light::SOFTSPOT: + glEnable(GL_LIGHT0 + n); + { + GLfloat pos[4] = { l->getFrame()->getLTM()->pos.x, l->getFrame()->getLTM()->pos.y, l->getFrame()->getLTM()->pos.z, 1.0f }; + GLfloat dir[4] = { l->getFrame()->getLTM()->at.x, l->getFrame()->getLTM()->at.y, l->getFrame()->getLTM()->at.z, 0.0f }; + glLightfv(GL_LIGHT0 + n, GL_POSITION, pos); + glLightfv(GL_LIGHT0 + n, GL_SPOT_DIRECTION, dir); + glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, (GLfloat*)&l->color); + glLightf(GL_LIGHT0 + n, GL_SPOT_CUTOFF, 45.0f); + } + bits |= VSLIGHT_SPOT; + n++; + if(n >= MAX_LIGHTS) goto out; + break; + } + } + +out: + if(n > 0 || lightData->numAmbients > 0) + glEnable(GL_LIGHTING); + else + glDisable(GL_LIGHTING); + + objectDirty = 1; + return bits;*/ +} + +void +setProjectionMatrix(float32 *mat) +{ + memcpy(&uniformScene.proj, mat, 64); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(uniformScene.proj); + sceneDirty = 1; +} + +void +setViewMatrix(float32 *mat) +{ + memcpy(&uniformScene.view, mat, 64); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(uniformScene.view); + glMultMatrixf((float*)&uniformObject.world); + sceneDirty = 1; +} + +void +setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp) +{ + rw::RGBAf col; + convColor(&col, &color); + glColor4f(col.red, col.green, col.blue, col.alpha); + + GLfloat ambient[4] = { col.red * surfaceprops.ambient, col.green * surfaceprops.ambient, col.blue * surfaceprops.ambient, col.alpha }; + GLfloat diffuse[4] = { col.red * surfaceprops.diffuse, col.green * surfaceprops.diffuse, col.blue * surfaceprops.diffuse, col.alpha }; + GLfloat specular[4] = { surfaceprops.specular, surfaceprops.specular, surfaceprops.specular, 1.0f }; + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); +} + +void flushCache(void){ + flushGlRenderState(); + + if(uniformStateDirty[RWGL_ALPHAFUNC] || uniformStateDirty[RWGL_ALPHAREF]){ + if (rwStateCache.alphaTestEnable) { + glEnable(GL_ALPHA_TEST); + int func = GL_ALWAYS; + switch(rwStateCache.alphaFunc){ + case ALPHAALWAYS: + func = GL_ALWAYS; + break; + case ALPHAGREATEREQUAL: + func = GL_GEQUAL; + break; + case ALPHALESS: + func = GL_LESS; + break; + } + glAlphaFunc(func, alphaRef); + } else { + glDisable(GL_ALPHA_TEST); + } + uniformStateDirty[RWGL_ALPHAFUNC] = false; + uniformStateDirty[RWGL_ALPHAREF] = false; + } + + if(uniformStateDirty[RWGL_FOG] || + uniformStateDirty[RWGL_FOGSTART] || + uniformStateDirty[RWGL_FOGEND] || + uniformStateDirty[RWGL_FOGCOLOR]){ + glDisable(GL_FOG); + if (rwStateCache.fogEnable) { + glEnable(GL_FOG); + glFogf(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_START, rwStateCache.fogStart); + glFogf(GL_FOG_END, rwStateCache.fogEnd); + GLfloat fcolor[4] = { uniformState.fogColor.red, uniformState.fogColor.green, uniformState.fogColor.blue, uniformState.fogColor.alpha }; + glFogfv(GL_FOG_COLOR, fcolor); + } else { + glDisable(GL_FOG); + } + uniformStateDirty[RWGL_FOG] = false; + uniformStateDirty[RWGL_FOGSTART] = false; + uniformStateDirty[RWGL_FOGEND] = false; + uniformStateDirty[RWGL_FOGCOLOR] = false; + } +} + +static void +setFrameBuffer(Camera *cam) +{ + Raster *fbuf = cam->frameBuffer->parent; + Raster *zbuf = cam->zBuffer->parent; + assert(fbuf); + + Gl1Raster *natfb = PLUGINOFFSET(Gl1Raster, fbuf, nativeRasterOffset); + Gl1Raster *natzb = PLUGINOFFSET(Gl1Raster, zbuf, nativeRasterOffset); + assert(fbuf->type == Raster::CAMERA || fbuf->type == Raster::CAMERATEXTURE); + + // Have to make sure depth buffer is attached to FB's fbo + bindFramebuffer(natfb->fbo); + if (zbuf) { + if(natfb->fboMate != zbuf){ +// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GETGL3RASTEREXT(zbuf)->texid); + natfb->fboMate = zbuf; + } + } else if(natfb->fboMate) { +// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + natfb->fboMate = nil; + } +} + +static Rect +getFramebufferRect(Raster *frameBuffer) +{ + Rect r; + Raster *fb = frameBuffer->parent; + if(fb->type == Raster::CAMERA){ + r.w = glGlobals.modes[0].width; + r.h = glGlobals.modes[0].height; + }else{ + r.w = fb->width; + r.h = fb->height; + } + r.x = 0; + r.y = 0; + + // Got a subraster + if(frameBuffer != fb){ + r.x = frameBuffer->offsetX; + // GL y offset is from bottom + r.y = r.h - frameBuffer->height - frameBuffer->offsetY; + r.w = frameBuffer->width; + r.h = frameBuffer->height; + } + + return r; +} + +static void +setViewport(Raster *frameBuffer) +{ + Rect r = getFramebufferRect(frameBuffer); + if(r.w != glGlobals.presentWidth || r.h != glGlobals.presentHeight || + r.x != glGlobals.presentOffX || r.y != glGlobals.presentOffY){ + glViewport(r.x, r.y, r.w, r.h); + glGlobals.presentWidth = r.w; + glGlobals.presentHeight = r.h; + glGlobals.presentOffX = r.x; + glGlobals.presentOffY = r.y; + } +} + +static void +beginUpdate(Camera *cam) +{ + float view[16], proj[16]; + // View Matrix + Matrix inv; + Matrix::invert(&inv, cam->getFrame()->getLTM()); + // Since we're looking into positive Z, + // flip X to ge a left handed view space. + view[0] = -inv.right.x; + view[1] = inv.right.y; + view[2] = inv.right.z; + view[3] = 0.0f; + view[4] = -inv.up.x; + view[5] = inv.up.y; + view[6] = inv.up.z; + view[7] = 0.0f; + view[8] = -inv.at.x; + view[9] = inv.at.y; + view[10] = inv.at.z; + view[11] = 0.0f; + view[12] = -inv.pos.x; + view[13] = inv.pos.y; + view[14] = inv.pos.z; + view[15] = 1.0f; + memcpy(&cam->devView, &view, sizeof(RawMatrix)); + setViewMatrix(view); + + // Projection Matrix + float32 invwx = 1.0f/cam->viewWindow.x; + float32 invwy = 1.0f/cam->viewWindow.y; + float32 invz = 1.0f/(cam->farPlane-cam->nearPlane); + + proj[0] = invwx; + proj[1] = 0.0f; + proj[2] = 0.0f; + proj[3] = 0.0f; + + proj[4] = 0.0f; + proj[5] = invwy; + proj[6] = 0.0f; + proj[7] = 0.0f; + + proj[8] = cam->viewOffset.x*invwx; + proj[9] = cam->viewOffset.y*invwy; + proj[12] = -proj[8]; + proj[13] = -proj[9]; + if(cam->projection == Camera::PERSPECTIVE){ + proj[10] = (cam->farPlane+cam->nearPlane)*invz; + proj[11] = 1.0f; + + proj[14] = -2.0f*cam->nearPlane*cam->farPlane*invz; + proj[15] = 0.0f; + }else{ + proj[10] = 2.0f*invz; + proj[11] = 0.0f; + + proj[14] = -(cam->farPlane+cam->nearPlane)*invz; + proj[15] = 1.0f; + } + memcpy(&cam->devProj, &proj, sizeof(RawMatrix)); + setProjectionMatrix(proj); + + if(rwStateCache.fogStart != cam->fogPlane){ + rwStateCache.fogStart = cam->fogPlane; + uniformStateDirty[RWGL_FOGSTART] = true; + stateDirty = 1; + } + if(rwStateCache.fogEnd != cam->farPlane){ + rwStateCache.fogEnd = cam->farPlane; + uniformStateDirty[RWGL_FOGEND] = true; + stateDirty = 1; + } + + setFrameBuffer(cam); + + setViewport(cam->frameBuffer); +} + +static void +endUpdate(Camera *cam) +{ +} + +static void +clearCamera(Camera *cam, RGBA *col, uint32 mode) +{ + RGBAf colf; + GLbitfield mask; + + setFrameBuffer(cam); + + // make sure we're only clearing the part of the framebuffer + // that is subrastered + bool setScissor = cam->frameBuffer != cam->frameBuffer->parent; + if(setScissor){ + Rect r = getFramebufferRect(cam->frameBuffer); + glScissor(r.x, r.y, r.w, r.h); + glEnable(GL_SCISSOR_TEST); + } + + convColor(&colf, col); + glClearColor(colf.red, colf.green, colf.blue, colf.alpha); + mask = 0; + if(mode & Camera::CLEARIMAGE) + mask |= GL_COLOR_BUFFER_BIT; + if(mode & Camera::CLEARZ) + mask |= GL_DEPTH_BUFFER_BIT; + if(mode & Camera::CLEARSTENCIL) + mask |= GL_STENCIL_BUFFER_BIT; + glDepthMask(GL_TRUE); + glClear(mask); + glDepthMask(rwStateCache.zwrite); + + if(setScissor) + glDisable(GL_SCISSOR_TEST); +} + +static void +showRaster(Raster *raster, uint32 flags) +{ +// glViewport(raster->offsetX, raster->offsetY, +// raster->width, raster->height); + // TODO check if context is lost + eglSwapBuffers(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW)); +} + +static bool32 +rasterRenderFast(Raster *raster, int32 x, int32 y) +{ + Raster *src = raster; + Raster *dst = Raster::getCurrentContext(); + Gl1Raster *natdst = PLUGINOFFSET(Gl1Raster, dst, nativeRasterOffset); + Gl1Raster *natsrc = PLUGINOFFSET(Gl1Raster, src, nativeRasterOffset); + + switch(dst->type){ + case Raster::NORMAL: + case Raster::TEXTURE: + case Raster::CAMERATEXTURE: + switch(src->type){ + case Raster::CAMERA: + setActiveTexture(0); + glBindTexture(GL_TEXTURE_2D, natdst->texid); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, (dst->height-src->height)-y, + 0, 0, src->width, src->height); + glBindTexture(GL_TEXTURE_2D, boundTexture[0]); + return 1; + } + break; + } + return 0; +} + +static int +openSymbian(EngineOpenParams *openparams) +{ + glGlobals.winWidth = openparams->width; + glGlobals.winHeight = openparams->height; + + glGlobals.modes = (DisplayMode*)rwMalloc(sizeof(DisplayMode), ID_DRIVER | MEMDUR_EVENT); + glGlobals.modes[0].width = openparams->width; + glGlobals.modes[0].height = openparams->height; + glGlobals.modes[0].depth = 32; + glGlobals.modes[0].flags = VIDEOMODEEXCLUSIVE; + + glGlobals.numModes = 1; + glGlobals.currentMode = 0; + + glGlobals.numMonitors = 1; + glGlobals.currentMonitor = 0; + + return 1; +} + +static int +closeSymbian(void) +{ + if(glGlobals.modes){ + rwFree(glGlobals.modes); + glGlobals.modes = nil; + } + return 1; +} + +static int +startSymbian(void) +{ + glGlobals.presentWidth = glGlobals.winWidth; + glGlobals.presentHeight = glGlobals.winHeight; + glGlobals.presentOffX = 0; + glGlobals.presentOffY = 0; + + return 1; +} + +static int +stopSymbian(void) +{ + return 1; +} + +static int +initOpenGL(void) +{ + glClearColor(0.25, 0.25, 0.25, 1.0); + + byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + glGenTextures(1, &whitetex); + glBindTexture(GL_TEXTURE_2D, whitetex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel); + + resetRenderState(); + + glEnable(GL_NORMALIZE); + + openIm2D(); + openIm3D(); + + return 1; +} + +static int +termOpenGL(void) +{ + closeIm3D(); + closeIm2D(); + + glDeleteTextures(1, &whitetex); + whitetex = 0; + + return 1; +} + +static int +finalizeOpenGL(void) +{ + return 1; +} + +static int +deviceSystemSymbian(DeviceReq req, void *arg, int32 n) +{ + VideoMode *rwmode; + + switch(req){ + case DEVICEOPEN: + return openSymbian((EngineOpenParams*)arg); + + case DEVICECLOSE: + return closeSymbian(); + + case DEVICEINIT: + return startSymbian() && initOpenGL(); + + case DEVICETERM: + return termOpenGL() && stopSymbian(); + + case DEVICEFINALIZE: + return finalizeOpenGL(); + + case DEVICEGETNUMSUBSYSTEMS: + return glGlobals.numMonitors; + + case DEVICEGETCURRENTSUBSYSTEM: + return glGlobals.currentMonitor; + + case DEVICESETSUBSYSTEM: + if(n >= glGlobals.numMonitors) + return 0; + glGlobals.currentMonitor = n; + return 1; + + case DEVICEGETSUBSSYSTEMINFO: + if(n >= glGlobals.numMonitors) + return 0; + strncpy(((SubSystemInfo*)arg)->name, "Symbian Display", 80 /*sizeof(SubSystemInfo::name)*/); + return 1; + + case DEVICEGETNUMVIDEOMODES: + return glGlobals.numModes; + + case DEVICEGETCURRENTVIDEOMODE: + return glGlobals.currentMode; + + case DEVICESETVIDEOMODE: + if(n >= glGlobals.numModes) + return 0; + glGlobals.currentMode = n; + return 1; + + case DEVICEGETVIDEOMODEINFO: + rwmode = (VideoMode*)arg; + rwmode->width = glGlobals.modes[n].width; + rwmode->height = glGlobals.modes[n].height; + rwmode->depth = glGlobals.modes[n].depth; + rwmode->flags = glGlobals.modes[n].flags; + return 1; + + case DEVICEGETMAXMULTISAMPLINGLEVELS: + return 1; + + case DEVICEGETMULTISAMPLINGLEVELS: + return 1; + + case DEVICESETMULTISAMPLINGLEVELS: + glGlobals.numSamples = 1; + return 1; + + default: + assert(0 && "not implemented"); + return 0; + } + return 1; +} + +Device renderdevice = { + -1.0f, 1.0f, + gles1::beginUpdate, + gles1::endUpdate, + gles1::clearCamera, + gles1::showRaster, + gles1::rasterRenderFast, + gles1::setRenderState, + gles1::getRenderState, + gles1::im2DRenderLine, + gles1::im2DRenderTriangle, + gles1::im2DRenderPrimitive, + gles1::im2DRenderIndexedPrimitive, + gles1::im3DTransform, + gles1::im3DRenderPrimitive, + gles1::im3DRenderIndexedPrimitive, + gles1::im3DEnd, + gles1::deviceSystemSymbian +}; + +} +} + +#else +// urgh, probably should get rid of that eventually +#include "rwgles1.h" +namespace rw { +namespace gles1 { +bool32 needToReadBackTextures; +} +} +#endif diff --git a/vendor/librw/src/gles1/gl1immed.cpp b/vendor/librw/src/gles1/gl1immed.cpp new file mode 100644 index 0000000..d9f7260 --- /dev/null +++ b/vendor/librw/src/gles1/gl1immed.cpp @@ -0,0 +1,243 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwrender.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#ifdef RW_GLES1 +#include "rwgles1.h" +#include "rwgles1impl.h" + +namespace rw { +namespace gles1 { + +uint32 im2DVbo, im2DIbo; + +static int primTypeMap[] = { + GL_POINTS, // invalid + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + GL_POINTS +}; + +void +openIm2D(void) +{ + glGenBuffers(1, &im2DIbo); + glGenBuffers(1, &im2DVbo); +} + +void +closeIm2D(void) +{ + glDeleteBuffers(1, &im2DIbo); + glDeleteBuffers(1, &im2DVbo); +} + +static Im2DVertex tmpprimbuf[3]; + +void +im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2) +{ + Im2DVertex *verts = (Im2DVertex*)vertices; + tmpprimbuf[0] = verts[vert1]; + tmpprimbuf[1] = verts[vert2]; + im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2); +} + +void +im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3) +{ + Im2DVertex *verts = (Im2DVertex*)vertices; + tmpprimbuf[0] = verts[vert1]; + tmpprimbuf[1] = verts[vert2]; + tmpprimbuf[2] = verts[vert3]; + im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3); +} + +void +im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices) +{ + Camera *cam; + cam = (Camera*)engine->currentCamera; + + glBindBuffer(GL_ARRAY_BUFFER, im2DVbo); + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_DYNAMIC_DRAW); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Im2DVertex), (void*)0); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Im2DVertex), (void*)OFFSET_OF(Im2DVertex, r)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(Im2DVertex), (void*)OFFSET_OF(Im2DVertex, u)); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glOrthof(0.0f, (float)cam->frameBuffer->width, (float)cam->frameBuffer->height, 0.0f, -1000.0f, 1000.0f); + + flushCache(); + + glDrawArrays(primTypeMap[primType], 0, numVertices); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void im2DRenderIndexedPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices, + void *indices, int32 numIndices) +{ + Camera *cam; + cam = (Camera*)engine->currentCamera; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, im2DVbo); + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_DYNAMIC_DRAW); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Im2DVertex), (void*)0); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Im2DVertex), (void*)OFFSET_OF(Im2DVertex, r)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(Im2DVertex), (void*)OFFSET_OF(Im2DVertex, u)); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrthof(0.0f, (float)cam->frameBuffer->width, (float)cam->frameBuffer->height, 0.0f, -1000.0f, 1000.0f); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + flushCache(); + glDrawElements(primTypeMap[primType], numIndices, GL_UNSIGNED_SHORT, nil); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +// Im3D + +static AttribDesc im3dattribDesc[3] = { + { ATTRIB_POS, GL_FLOAT, GL_FALSE, 3, + sizeof(Im3DVertex), 0 }, + { ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4, + sizeof(Im3DVertex), OFFSET_OF(Im3DVertex, r) }, + { ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2, + sizeof(Im3DVertex), OFFSET_OF(Im3DVertex, u) }, +}; +static uint32 im3DVbo, im3DIbo; +static int32 num3DVertices; // not actually needed here +static void* currentIm3dVertices; + +void +openIm3D(void) +{ + glGenBuffers(1, &im3DIbo); + glGenBuffers(1, &im3DVbo); +} + +void +closeIm3D(void) +{ + glDeleteBuffers(1, &im3DIbo); + glDeleteBuffers(1, &im3DVbo); +} + +void +im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) +{ + if(world == nil){ + static Matrix ident; + ident.setIdentity(); + world = &ident; + } + setWorldMatrix(world); + + if((flags & im3d::VERTEXUV) == 0) + SetRenderStatePtr(TEXTURERASTER, nil); + + glBindBuffer(GL_ARRAY_BUFFER, im3DVbo); + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im3DVertex), vertices, GL_DYNAMIC_DRAW); + num3DVertices = numVertices; +} + +void +im3DRenderPrimitive(PrimitiveType primType) +{ + glBindBuffer(GL_ARRAY_BUFFER, im3DVbo); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Im3DVertex), (void*)0); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Im3DVertex), (void*)OFFSET_OF(Im3DVertex, r)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(Im3DVertex), (void*)OFFSET_OF(Im3DVertex, u)); + + flushCache(); + glDrawArrays(primTypeMap[primType], 0, num3DVertices); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void +im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices) +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, im3DVbo); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Im3DVertex), (void*)0); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Im3DVertex), (void*)OFFSET_OF(Im3DVertex, r)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(Im3DVertex), (void*)OFFSET_OF(Im3DVertex, u)); + + flushCache(); + glDrawElements(primTypeMap[primType], numIndices, GL_UNSIGNED_SHORT, nil); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void +im3DEnd(void) +{ +} + +} +} + +#endif diff --git a/vendor/librw/src/gles1/gl1matfx.cpp b/vendor/librw/src/gles1/gl1matfx.cpp new file mode 100644 index 0000000..b6a8f77 --- /dev/null +++ b/vendor/librw/src/gles1/gl1matfx.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwrender.h" +#include "../rwanim.h" +#include "../rwplugins.h" +#include "rwgles1.h" +#include "rwgles1plg.h" +#include "rwgles1impl.h" + +#ifdef RW_GLES1 + +namespace rw { +namespace gles1 { + +void +matfxRenderCB(Atomic *atomic, InstanceDataHeader *header) +{ + uint32 flags = atomic->geometry->flags; + setWorldMatrix(atomic->getFrame()->getLTM()); + glDisable(GL_LIGHTING); + + setupVertexInput(header); + + InstanceData *inst = header->inst; + int32 n = header->numMeshes; + + while(n--){ + MatFX *matfx = MatFX::get(inst->material); + Material *m = inst->material; + + // En GLES1 sin shaders: ignoramos env map, solo dibujamos textura base + setMaterial(flags, m->color, m->surfaceProps); + setTexture(0, m->texture); + rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF); + drawInst(header, inst); + inst++; + } + + teardownVertexInput(header); +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + ObjPipeline *pipe = ObjPipeline::create(); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = matfxRenderCB; + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + return pipe; +} + +static void* +matfxOpen(void *o, int32, int32) +{ + matFXGlobals.pipelines[PLATFORM_GLES1] = makeMatFXPipeline(); + return o; +} + +static void* +matfxClose(void *o, int32, int32) +{ + ((ObjPipeline*)matFXGlobals.pipelines[PLATFORM_GLES1])->destroy(); + matFXGlobals.pipelines[PLATFORM_GLES1] = nil; + return o; +} + +void +initMatFX(void) +{ + Driver::registerPlugin(PLATFORM_GLES1, 0, ID_MATFX, matfxOpen, matfxClose); +} + +} +} + +#endif diff --git a/vendor/librw/src/gles1/gl1pipe.cpp b/vendor/librw/src/gles1/gl1pipe.cpp new file mode 100644 index 0000000..4750375 --- /dev/null +++ b/vendor/librw/src/gles1/gl1pipe.cpp @@ -0,0 +1,319 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" + +#include "rwgles1.h" + +namespace rw { +namespace gles1 { + +// TODO: make some of these things platform-independent + +#ifdef RW_GLES1 + +void +freeInstanceData(Geometry *geometry) +{ + if(geometry->instData == nil || + geometry->instData->platform != PLATFORM_GLES1) + return; + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + geometry->instData = nil; + glDeleteBuffers(1, &header->ibo); + glDeleteBuffers(1, &header->vbo); + rwFree(header->indexBuffer); + rwFree(header->vertexBuffer); + rwFree(header->attribDesc); + rwFree(header->inst); + rwFree(header); +} + +void* +destroyNativeData(void *object, int32, int32) +{ + freeInstanceData((Geometry*)object); + return object; +} + +static InstanceDataHeader* +instanceMesh(rw::ObjPipeline *rwpipe, Geometry *geo) +{ + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); + MeshHeader *meshh = geo->meshHeader; + geo->instData = header; + header->platform = PLATFORM_GLES1; + + header->serialNumber = meshh->serialNum; + header->numMeshes = meshh->numMeshes; + header->primType = meshh->flags == 1 ? GL_TRIANGLE_STRIP : GL_TRIANGLES; + header->totalNumVertex = geo->numVertices; + header->totalNumIndex = meshh->totalIndices; + header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); + + header->indexBuffer = rwNewT(uint16, header->totalNumIndex, MEMDUR_EVENT | ID_GEOMETRY); + InstanceData *inst = header->inst; + Mesh *mesh = meshh->getMeshes(); + uint32 offset = 0; + for(uint32 i = 0; i < header->numMeshes; i++){ + findMinVertAndNumVertices(mesh->indices, mesh->numIndices, + &inst->minVert, &inst->numVertices); + assert(inst->minVert != 0xFFFFFFFF); + inst->numIndex = mesh->numIndices; + inst->material = mesh->material; + inst->vertexAlpha = 0; + inst->program = 0; + inst->offset = offset; + memcpy((uint8*)header->indexBuffer + inst->offset, + mesh->indices, inst->numIndex*2); + offset += inst->numIndex*2; + mesh++; + inst++; + } + + header->vertexBuffer = nil; + header->numAttribs = 0; + header->attribDesc = nil; + header->ibo = 0; + header->vbo = 0; + + glGenBuffers(1, &header->ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, header->totalNumIndex*2, + header->indexBuffer, GL_STATIC_DRAW); + + return header; +} + +static void +instance(rw::ObjPipeline *rwpipe, Atomic *atomic) +{ + ObjPipeline *pipe = (ObjPipeline*)rwpipe; + Geometry *geo = atomic->geometry; + // don't try to (re)instance native data + if(geo->flags & Geometry::NATIVE) + return; + + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + if(geo->instData){ + // Already have instanced data, so check if we have to reinstance + assert(header->platform == PLATFORM_GLES1); + if(header->serialNumber != geo->meshHeader->serialNum){ + // Mesh changed, so reinstance everything + freeInstanceData(geo); + } + } + + // no instance or complete reinstance + if(geo->instData == nil){ + geo->instData = instanceMesh(rwpipe, geo); + pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 0); + }else if(geo->lockedSinceInst) + pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 1); + + geo->lockedSinceInst = 0; +} + +static void +uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) +{ + assert(0 && "can't uninstance"); +} + +static void render(rw::ObjPipeline *rwpipe, Atomic *atomic){ + ObjPipeline *pipe = (ObjPipeline*)rwpipe; + Geometry *geo = atomic->geometry; + pipe->instance(atomic); + assert(geo->instData != nil); + assert(geo->instData->platform == PLATFORM_GLES1); + if(pipe->renderCB) + pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData); + else { + FILE *f = fopen("E:\\re3_debug.txt", "a"); + if(f){ fprintf(f, "render: renderCB is nil!\n"); fclose(f); } + } +} + +void +ObjPipeline::init(void) +{ + this->rw::ObjPipeline::init(PLATFORM_GLES1); + this->impl.instance = gles1::instance; + this->impl.uninstance = gles1::uninstance; + this->impl.render = gles1::render; + this->instanceCB = nil; + this->uninstanceCB = nil; + this->renderCB = nil; +} + +ObjPipeline* +ObjPipeline::create(void) +{ + ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL); + pipe->init(); + return pipe; +} + +void +defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) +{ + AttribDesc *attribs, *a; + + bool isPrelit = !!(geo->flags & Geometry::PRELIT); + bool hasNormals = !!(geo->flags & Geometry::NORMALS); + + if(!reinstance){ + AttribDesc tmpAttribs[12]; + uint32 stride; + + // + // Create attribute descriptions + // + a = tmpAttribs; + stride = 0; + + // Positions + a->index = ATTRIB_POS; + a->size = 3; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 12; + a++; + + // Normals + // TODO: compress + if(hasNormals){ + a->index = ATTRIB_NORMAL; + a->size = 3; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 12; + a++; + } + + // Prelighting + if(isPrelit){ + a->index = ATTRIB_COLOR; + a->size = 4; + a->type = GL_UNSIGNED_BYTE; + a->normalized = GL_TRUE; + a->offset = stride; + stride += 4; + a++; + } + + // Texture coordinates + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + a->index = ATTRIB_TEXCOORDS0+n; + a->size = 2; + a->type = GL_FLOAT; + a->normalized = GL_FALSE; + a->offset = stride; + stride += 8; + a++; + } + + header->numAttribs = a - tmpAttribs; + for(a = tmpAttribs; a != &tmpAttribs[header->numAttribs]; a++) + a->stride = stride; + header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); + memcpy(header->attribDesc, tmpAttribs, + header->numAttribs*sizeof(AttribDesc)); + + // + // Allocate vertex buffer + // + header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); + assert(header->vbo == 0); + glGenBuffers(1, &header->vbo); + } + + attribs = header->attribDesc; + + // + // Fill vertex buffer + // + + uint8 *verts = header->vertexBuffer; + + // Positions + if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){ + for(a = attribs; a->index != ATTRIB_POS; a++) + ; + instV3d(VERT_FLOAT3, verts + a->offset, + geo->morphTargets[0].vertices, + header->totalNumVertex, a->stride); + } + + // Normals + if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){ + for(a = attribs; a->index != ATTRIB_NORMAL; a++) + ; + instV3d(VERT_FLOAT3, verts + a->offset, + geo->morphTargets[0].normals, + header->totalNumVertex, a->stride); + } + + // Prelighting + if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){ + for(a = attribs; a->index != ATTRIB_COLOR; a++) + ; + int n = header->numMeshes; + InstanceData *inst = header->inst; + while(n--){ + assert(inst->minVert != 0xFFFFFFFF); + inst->vertexAlpha = instColor(VERT_RGBA, + verts + a->offset + a->stride*inst->minVert, + geo->colors + inst->minVert, + inst->numVertices, a->stride); + inst++; + } + } + + // Texture coordinates + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<index != ATTRIB_TEXCOORDS0+n; a++) + ; + instTexCoords(VERT_FLOAT2, verts + a->offset, + geo->texCoords[n], + header->totalNumVertex, a->stride); + } + } + + glBindBuffer(GL_ARRAY_BUFFER, header->vbo); + glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*attribs[0].stride, + header->vertexBuffer, GL_STATIC_DRAW); +} + +void +defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header) +{ + assert(0 && "can't uninstance"); +} + +ObjPipeline* +makeDefaultPipeline(void) +{ + ObjPipeline *pipe = ObjPipeline::create(); + pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; + pipe->renderCB = defaultRenderCB; + return pipe; +} + +#else +void *destroyNativeData(void *object, int32, int32) { return object; } +#endif + +} +} diff --git a/vendor/librw/src/gles1/gl1raster.cpp b/vendor/librw/src/gles1/gl1raster.cpp new file mode 100644 index 0000000..bca261a --- /dev/null +++ b/vendor/librw/src/gles1/gl1raster.cpp @@ -0,0 +1,934 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" + +#include "rwgles1.h" +#include "rwgles1impl.h" + +#define PLUGIN_ID ID_DRIVER + +namespace rw { +namespace gles1 { + +int32 nativeRasterOffset; + +static uint32 +getLevelSize(Raster *raster, int32 level) +{ + int i; + Gl1Raster *natras = GETGL1RASTEREXT(raster); + + int w = raster->originalWidth; + int h = raster->originalHeight; + int s = raster->originalStride; + int minDim = 1; + +//#ifdef RW_GLES1 +// switch(natras->internalFormat){ +// case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: +// case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: +// case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: +// case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: +// minDim = 4; +// break; +// } +//#endif + + for(i = 0; i < level; i++){ + if(w > minDim){ + w /= 2; + s /= 2; + } + if(h > minDim) + h /= 2; + } + + return s*h; +} + +#ifdef RW_GLES1 + +static Raster* +rasterCreateTexture(Raster *raster) +{ + if(raster->format & (Raster::PAL4 | Raster::PAL8)){ + RWERROR((ERR_NOTEXTURE)); + return nil; + } + + Gl1Raster *natras = GETGL1RASTEREXT(raster); + switch(raster->format & 0xF00){ + case Raster::C8888: + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 1; + natras->bpp = 4; + raster->depth = 32; + break; + case Raster::C888: + natras->internalFormat = GL_RGB; + natras->format = GL_RGB; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 0; + natras->bpp = 3; + raster->depth = 24; + break; + case Raster::C565: + natras->internalFormat = GL_RGB; + natras->format = GL_RGB; + natras->type = GL_UNSIGNED_SHORT_5_6_5; + natras->hasAlpha = 0; + natras->bpp = 2; + raster->depth = 16; + break; + case Raster::C4444: + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_SHORT_4_4_4_4; + natras->hasAlpha = 1; + natras->bpp = 2; + raster->depth = 16; + break; + case Raster::C1555: +// natras->internalFormat = GL_RGB5_A1; + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_SHORT_5_5_5_1; + natras->hasAlpha = 1; + natras->bpp = 2; + raster->depth = 16; + break; + default: + RWERROR((ERR_INVRASTER)); + return nil; + } + + natras->internalFormat = natras->format; + + raster->stride = raster->width*natras->bpp; + + if(raster->format & Raster::MIPMAP){ + int w = raster->width; + int h = raster->height; + natras->numLevels = 1; + while(w != 1 || h != 1){ + natras->numLevels++; + if(w > 1) w /= 2; + if(h > 1) h /= 2; + } + } + natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP); + if(natras->autogenMipmap) + natras->numLevels = 1; + + glGenTextures(1, &natras->texid); + uint32 prev = bindTexture(natras->texid); +// glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, +//// raster->width, raster->height, +// 1,1, +// 0, natras->format, natras->type, nil); + // TODO: allocate other levels...probably + natras->filterMode = 0; + natras->addressU = 0; + natras->addressV = 0; + natras->maxAnisotropy = 1; + + bindTexture(prev); + return raster; +} + +static Raster* +rasterCreateCameraTexture(Raster *raster) +{ + if(raster->format & (Raster::PAL4 | Raster::PAL8)){ + RWERROR((ERR_NOTEXTURE)); + return nil; + } + + // TODO: figure out what the backbuffer is and use that as a default + Gl1Raster *natras = GETGL1RASTEREXT(raster); + switch(raster->format & 0xF00){ + case Raster::C8888: + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 1; + natras->bpp = 4; + break; + case Raster::C4444: + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_SHORT_4_4_4_4; + natras->hasAlpha = 1; + natras->bpp = 2; + break; + case Raster::C888: + default: + natras->internalFormat = GL_RGB; + natras->format = GL_RGB; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 0; + natras->bpp = 3; + break; + case Raster::C565: + natras->internalFormat = GL_RGB; + natras->format = GL_RGB; + natras->type = GL_UNSIGNED_SHORT_5_6_5; + natras->hasAlpha = 0; + natras->bpp = 2; + break; + case Raster::C1555: +// natras->internalFormat = GL_RGB5_A1; + natras->internalFormat = GL_RGBA; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_SHORT_5_5_5_1; + natras->hasAlpha = 1; + natras->bpp = 2; + break; + } + + natras->internalFormat = natras->format; + + raster->stride = raster->width*natras->bpp; + + natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP); + + glGenTextures(1, &natras->texid); + uint32 prev = bindTexture(natras->texid); + glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, +// raster->width, raster->height, + 1,1, + 0, natras->format, natras->type, nil); + natras->filterMode = 0; + natras->addressU = 0; + natras->addressV = 0; + natras->maxAnisotropy = 1; + + bindTexture(prev); + + +// glGenFramebuffers(1, &natras->fbo); +// bindFramebuffer(natras->fbo); +// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0); +// bindFramebuffer(0); + natras->fboMate = nil; + + return raster; +} + +static Raster* +rasterCreateCamera(Raster *raster) +{ + Gl1Raster *natras = GETGL1RASTEREXT(raster); + + // TODO: set/check width, height, depth, format? + + // used for locking right now +// raster->format = Raster::C888; +// natras->internalFormat = GL_RGB; +// natras->format = GL_RGB; +// natras->type = GL_UNSIGNED_BYTE; +// natras->hasAlpha = 0; +// natras->bpp = 3; +// +// natras->autogenMipmap = 0; + + raster->originalWidth = raster->width; + raster->originalHeight = raster->height; + raster->stride = 0; + raster->pixels = nil; + + natras->texid = 0; + natras->fbo = 0; + natras->fboMate = nil; + + return raster; +} + +static Raster* +rasterCreateZbuffer(Raster *raster) +{ + Gl1Raster *natras = GETGL1RASTEREXT(raster); + + raster->originalWidth = raster->width; + raster->originalHeight = raster->height; + raster->stride = 0; + raster->pixels = nil; + return raster; +} +#endif + +/* +{ 0, 0, 0 }, +{ 16, 4, GL_RGBA }, // 1555 +{ 16, 3, GL_RGB }, // 565 +{ 16, 4, GL_RGBA }, // 4444 +{ 0, 0, 0 }, // LUM8 +{ 32, 4, GL_RGBA }, // 8888 +{ 24, 3, GL_RGB }, // 888 +{ 16, 3, GL_RGB }, // D16 +{ 24, 3, GL_RGB }, // D24 +{ 32, 4, GL_RGBA }, // D32 +{ 16, 3, GL_RGB }, // 555 + +0, +GL_RGB5_A1, +GL_RGB5, +GL_RGBA4, +0, +GL_RGBA8, +GL_RGB8, +GL_RGB5, +GL_RGB8, +GL_RGBA8, +GL_RGB5 +*/ + +Raster* +rasterCreate(Raster *raster) +{ + Gl1Raster *natras = GETGL1RASTEREXT(raster); + + natras->isCompressed = 0; + natras->hasAlpha = 0; + natras->numLevels = 1; + + Raster *ret = raster; + + if(raster->width == 0 || raster->height == 0){ + raster->flags |= Raster::DONTALLOCATE; + raster->stride = 0; + goto ret; + } + if(raster->flags & Raster::DONTALLOCATE) + goto ret; + + switch(raster->type){ +#ifdef RW_GLES1 + case Raster::NORMAL: + case Raster::TEXTURE: + ret = rasterCreateTexture(raster); + break; + case Raster::CAMERATEXTURE: + ret = rasterCreateCameraTexture(raster); + break; + case Raster::ZBUFFER: + ret = rasterCreateZbuffer(raster); + break; + case Raster::CAMERA: + ret = rasterCreateCamera(raster); + break; +#endif + + default: + RWERROR((ERR_INVRASTER)); + return nil; + } + +ret: + raster->originalWidth = raster->width; + raster->originalHeight = raster->height; + raster->originalStride = raster->stride; + raster->originalPixels = raster->pixels; + return ret; +} + +uint8* +rasterLock(Raster *raster, int32 level, int32 lockMode) +{ +#ifdef RW_GLES1 + Gl1Raster *natras = GETGL1RASTEREXT(raster); + uint8 *px; + uint32 allocSz; + int i; + + assert(raster->privateFlags == 0); + + switch(raster->type){ + case Raster::NORMAL: + case Raster::TEXTURE: + case Raster::CAMERATEXTURE: + for(i = 0; i < level; i++){ + if(raster->width > 1){ + raster->width /= 2; + raster->stride /= 2; + } + if(raster->height > 1) + raster->height /= 2; + } + + allocSz = getLevelSize(raster, level); + px = (uint8*)rwMalloc(allocSz, MEMDUR_EVENT | ID_DRIVER); + assert(raster->pixels == nil); + raster->pixels = px; + + if(lockMode & Raster::LOCKREAD || !(lockMode & Raster::LOCKNOFETCH)){ + if(natras->backingStore){ + assert(level < natras->backingStore->numlevels); + assert(allocSz >= natras->backingStore->levels[level].size); + memcpy(px, natras->backingStore->levels[level].data, allocSz); + } else { + memset(px, 0, allocSz); + } + } + + raster->privateFlags = lockMode; + break; + + case Raster::CAMERA: + if(lockMode & Raster::PRIVATELOCK_WRITE) + assert(0 && "can't lock framebuffer for writing"); + raster->width = glGlobals.presentWidth; + raster->height = glGlobals.presentHeight; + raster->stride = raster->width*natras->bpp; + assert(natras->bpp == 3); + allocSz = raster->height*raster->stride; + px = (uint8*)rwMalloc(allocSz, MEMDUR_EVENT | ID_DRIVER); + assert(raster->pixels == nil); + raster->pixels = px; +#ifdef __SYMBIAN32__ + memset(px, 0, allocSz); +#else + glReadBuffer(GL_BACK); +#endif + glReadPixels(0, 0, raster->width, raster->height, GL_RGB, GL_UNSIGNED_BYTE, px); + + raster->privateFlags = lockMode; + break; + + default: + assert(0 && "cannot lock this type of raster yet"); + return nil; + } + + return px; +#else + return nil; +#endif +} + +void rasterUnlock(Raster *raster, int32 level){ +#ifdef RW_GLES1 + Gl1Raster *natras = GETGL1RASTEREXT(raster); + + assert(raster->pixels); + + switch(raster->type){ + case Raster::NORMAL: + case Raster::TEXTURE: + case Raster::CAMERATEXTURE: + if(raster->privateFlags & Raster::LOCKWRITE){ + if(level != 0) break; + + // === GUARDAR EN BACKING STORE ANTES DE SUBIR A GPU === + if(natras->backingStore == nil){ + int numLevels = natras->numLevels; + // RasterLevels tiene: int numlevels; struct { uint32 size; uint8 *data; } levels[]; + natras->backingStore = (RasterLevels*)malloc( + sizeof(RasterLevels) + sizeof(natras->backingStore->levels[0]) * numLevels); + natras->backingStore->numlevels = numLevels; + for(int i = 0; i < numLevels; i++){ + uint32 sz = getLevelSize(raster, i); + natras->backingStore->levels[i].size = sz; + natras->backingStore->levels[i].data = (uint8*)malloc(sz); + memset(natras->backingStore->levels[i].data, 0, sz); + } + } + // copiar píxeles actuales al backing store + { + uint32 sz = getLevelSize(raster, level); + assert(level < natras->backingStore->numlevels); + memcpy(natras->backingStore->levels[level].data, raster->pixels, sz); + } + // === FIN BACKING STORE === + + uint32 prev = bindTexture(natras->texid); + + // flip vertical (igual que antes) + { + int stride = raster->width * natras->bpp; + uint8_t *tmp = (uint8_t*)malloc(stride); + for(int y = 0; y < raster->height / 2; y++){ + uint8_t *a = (uint8_t*)raster->pixels + y * stride; + uint8_t *b = (uint8_t*)raster->pixels + (raster->height - 1 - y) * stride; + memcpy(tmp, a, stride); + memcpy(a, b, stride); + memcpy(b, tmp, stride); + } + free(tmp); + } + + if(!natras->isCompressed){ + if(natras->format == GL_RGBA && natras->type == GL_UNSIGNED_BYTE){ + // convertir RGBA8888 → RGBA4444 + uint16_t *pixels16 = (uint16_t*)malloc(raster->width * raster->height * 2); + uint8_t *pixels8 = (uint8_t*)raster->pixels; + for(int i = 0; i < raster->width * raster->height; i++){ + uint8_t r = pixels8[i*4+0]; + uint8_t g = pixels8[i*4+1]; + uint8_t b = pixels8[i*4+2]; + uint8_t a = pixels8[i*4+3]; + pixels16[i] = ((r>>4)<<12)|((g>>4)<<8)|((b>>4)<<4)|(a>>4); + } + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, + raster->width, raster->height, 0, + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels16); + free(pixels16); + } else { + glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, + raster->width, raster->height, 0, + natras->format, natras->type, raster->pixels); + } + } + + bindTexture(prev); + } + break; + + case Raster::CAMERA: + break; + } + + rwFree(raster->pixels); + raster->pixels = nil; +#endif + raster->width = raster->originalWidth; + raster->height = raster->originalHeight; + raster->stride = raster->originalStride; + raster->pixels = raster->originalPixels; + raster->privateFlags = 0; +} + +int32 +rasterNumLevels(Raster *raster) +{ + return GETGL1RASTEREXT(raster)->numLevels; +} + +// Almost the same as d3d9 and ps2 function +bool32 +imageFindRasterFormat(Image *img, int32 type, + int32 *pWidth, int32 *pHeight, int32 *pDepth, int32 *pFormat) +{ + int32 width, height, depth, format; + + assert((type&0xF) == Raster::TEXTURE); + +// for(width = 1; width < img->width; width <<= 1); +// for(height = 1; height < img->height; height <<= 1); + // Perhaps non-power-of-2 textures are acceptable? + width = img->width; + height = img->height; + + depth = img->depth; + + if(depth <= 8) + depth = 32; + + switch(depth){ + case 32: + if(img->hasAlpha()) + format = Raster::C8888; + else{ + format = Raster::C888; + depth = 24; + } + break; + case 24: + format = Raster::C888; + break; + case 16: + format = Raster::C1555; + break; + + case 8: + case 4: + default: + RWERROR((ERR_INVRASTER)); + return 0; + } + + format |= type; + + *pWidth = width; + *pHeight = height; + *pDepth = depth; + *pFormat = format; + + return 1; +} + +bool32 +rasterFromImage(Raster *raster, Image *image) +{ + if((raster->type&0xF) != Raster::TEXTURE) + return 0; + + void (*conv)(uint8 *out, uint8 *in) = nil; + + // Unpalettize image if necessary but don't change original + Image *truecolimg = nil; + if(image->depth <= 8){ + truecolimg = Image::create(image->width, image->height, image->depth); + truecolimg->pixels = image->pixels; + truecolimg->stride = image->stride; + truecolimg->palette = image->palette; + truecolimg->unpalettize(); + image = truecolimg; + } + + Gl1Raster *natras = GETGL1RASTEREXT(raster); + int32 format = raster->format&0xF00; + assert(!natras->isCompressed); + switch(image->depth){ + case 32: + if(format == Raster::C8888) + conv = conv_RGBA8888_from_RGBA8888; + else if(format == Raster::C888) + conv = conv_RGB888_from_RGB888; + else + goto err; + break; + case 24: + if(format == Raster::C8888) + conv = conv_RGBA8888_from_RGB888; + else if(format == Raster::C888) + conv = conv_RGB888_from_RGB888; + else + goto err; + break; + case 16: + if(format == Raster::C8888) + conv = conv_RGBA8888_from_ARGB1555; + else if(format == Raster::C1555) + conv = conv_RGBA5551_from_ARGB1555; + else + goto err; + break; + + case 8: + case 4: + default: + err: + RWERROR((ERR_INVRASTER)); + return 0; + } + + natras->hasAlpha = image->hasAlpha(); + + bool unlock = false; + if(raster->pixels == nil){ + raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH); + unlock = true; + } + + uint8 *pixels = raster->pixels; + assert(pixels); + uint8 *imgpixels = image->pixels + (image->height-1)*image->stride; + + int x, y; + assert(image->width == raster->width); + assert(image->height == raster->height); + for(y = 0; y < image->height; y++){ + uint8 *imgrow = imgpixels; + uint8 *rasrow = pixels; + for(x = 0; x < image->width; x++){ + conv(rasrow, imgrow); + imgrow += image->bpp; + rasrow += natras->bpp; + } + imgpixels -= image->stride; + pixels += raster->stride; + } + if(unlock) + raster->unlock(0); + + if(truecolimg) + truecolimg->destroy(); + + return 1; +} + +Image* +rasterToImage(Raster *raster) +{ + int32 depth; + Image *image; + + bool unlock = false; + if(raster->pixels == nil){ + raster->lock(0, Raster::LOCKREAD); + unlock = true; + } + + Gl1Raster *natras = GETGL1RASTEREXT(raster); + if(natras->isCompressed){ + // TODO + RWERROR((ERR_INVRASTER)); + return nil; + } + + void (*conv)(uint8 *out, uint8 *in) = nil; + switch(raster->format & 0xF00){ + case Raster::C1555: + depth = 16; + conv = conv_ARGB1555_from_RGBA5551; + break; + case Raster::C8888: + depth = 32; + conv = conv_RGBA8888_from_RGBA8888; + break; + case Raster::C888: + depth = 24; + conv = conv_RGB888_from_RGB888; + break; + + default: + case Raster::C555: + case Raster::C565: + case Raster::C4444: + case Raster::LUM8: + RWERROR((ERR_INVRASTER)); + return nil; + } + + if(raster->format & Raster::PAL4 || + raster->format & Raster::PAL8){ + RWERROR((ERR_INVRASTER)); + return nil; + } + + uint8 *in, *out; + image = Image::create(raster->width, raster->height, depth); + image->allocate(); + + uint8 *imgpixels = image->pixels + (image->height-1)*image->stride; + uint8 *pixels = raster->pixels; + + int x, y; + assert(image->width == raster->width); + assert(image->height == raster->height); + for(y = 0; y < image->height; y++){ + uint8 *imgrow = imgpixels; + uint8 *rasrow = pixels; + for(x = 0; x < image->width; x++){ + conv(imgrow, rasrow); + imgrow += image->bpp; + rasrow += natras->bpp; + } + imgpixels -= image->stride; + pixels += raster->stride; + } + + if(unlock) + raster->unlock(0); + + return image; +} + +static void* +createNativeRaster(void *object, int32 offset, int32) +{ + Gl1Raster *ras = PLUGINOFFSET(Gl1Raster, object, offset); + ras->texid = 0; + ras->fbo = 0; + ras->fboMate = nil; + ras->backingStore = nil; + return object; +} + +void evictRaster(Raster *raster); + +static void* +destroyNativeRaster(void *object, int32 offset, int32) +{ + Raster *raster = (Raster*)object; + Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, object, offset); +#ifdef RW_GLES1 + evictRaster(raster); + switch(raster->type){ + case Raster::NORMAL: + case Raster::TEXTURE: + glDeleteTextures(1, &natras->texid); + break; + + case Raster::CAMERATEXTURE: + break; + + case Raster::ZBUFFER: + break; + + case Raster::CAMERA: + if(natras->fboMate){ + // Break apart from currently associated zbuffer + Gl1Raster *zras = GETGL1RASTEREXT(natras->fboMate); + zras->fboMate = nil; + natras->fboMate = nil; + } + break; + } + natras->texid = 0; + natras->fbo = 0; + + if(natras->backingStore){ + for(int i = 0; i < natras->backingStore->numlevels; i++) + free(natras->backingStore->levels[i].data); + free(natras->backingStore); + natras->backingStore = nil; + } +#endif + return object; +} + +static void* +copyNativeRaster(void *dst, void *, int32 offset, int32) +{ + Gl1Raster *d = PLUGINOFFSET(Gl1Raster, dst, offset); + d->texid = 0; + d->fbo = 0; + d->fboMate = nil; + d->backingStore = nil; + return dst; +} + +Texture* +readNativeTexture(Stream *stream) +{ + uint32 platform; + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } + platform = stream->readU32(); + if(platform != PLATFORM_GLES1){ + RWERROR((ERR_PLATFORM, platform)); + return nil; + } + Texture *tex = Texture::create(nil); + if(tex == nil) + return nil; + + // Texture + tex->filterAddressing = stream->readU32(); + stream->read8(tex->name, 32); + stream->read8(tex->mask, 32); + + // Raster + uint32 format = stream->readU32(); + int32 width = stream->readI32(); + int32 height = stream->readI32(); + int32 depth = stream->readI32(); + int32 numLevels = stream->readI32(); + + // Native raster + int32 subplatform = stream->readI32(); + int32 flags = stream->readI32(); + int32 compression = stream->readI32(); + + Raster *raster; + Gl1Raster *natras; + if(flags & 2){ + tex->destroy(); + RWERROR((ERR_FORMAT_UNSUPPORTED)); + return nil; + }else{ + raster = Raster::create(width, height, depth, format | Raster::TEXTURE, PLATFORM_GLES1); + } + assert(raster); + natras = GETGL1RASTEREXT(raster); + tex->raster = raster; + + uint32 size; + uint8 *data; + for(int32 i = 0; i < numLevels; i++){ + size = stream->readU32(); + data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH); + stream->read8(data, size); + raster->unlock(i); + } + return tex; +} + +void +writeNativeTexture(Texture *tex, Stream *stream) +{ + Raster *raster = tex->raster; + Gl1Raster *natras = GETGL1RASTEREXT(raster); + + int32 chunksize = getSizeNativeTexture(tex); + writeChunkHeader(stream, ID_STRUCT, chunksize-12); + stream->writeU32(PLATFORM_GLES1); + + // Texture + stream->writeU32(tex->filterAddressing); + stream->write8(tex->name, 32); + stream->write8(tex->mask, 32); + + // Raster + int32 numLevels = natras->numLevels; + stream->writeI32(raster->format); + stream->writeI32(raster->width); + stream->writeI32(raster->height); + stream->writeI32(raster->depth); + stream->writeI32(numLevels); + + // Native raster + int32 flags = 0; + int32 compression = 0; + if(natras->hasAlpha) + flags |= 1; + if(natras->isCompressed){ + flags |= 2; + switch(natras->internalFormat){ + default: + assert(0 && "unknown compression"); + } + } + stream->writeI32(1); + stream->writeI32(flags); + stream->writeI32(compression); + // TODO: auto mipmaps? + + uint32 size; + uint8 *data; + for(int32 i = 0; i < numLevels; i++){ + size = getLevelSize(raster, i); + stream->writeU32(size); + data = raster->lock(i, Raster::LOCKREAD); + stream->write8(data, size); + raster->unlock(i); + } +} + +uint32 +getSizeNativeTexture(Texture *tex) +{ + uint32 size = 12 + 72 + 32; + int32 levels = tex->raster->getNumLevels(); + for(int32 i = 0; i < levels; i++) + size += 4 + getLevelSize(tex->raster, i); + return size; +} + + + +void registerNativeRaster(void) +{ + nativeRasterOffset = Raster::registerPlugin(sizeof(Gl1Raster), + ID_RASTERGLES1, + createNativeRaster, + destroyNativeRaster, + copyNativeRaster); +} + +} +} diff --git a/vendor/librw/src/gles1/gl1render.cpp b/vendor/librw/src/gles1/gl1render.cpp new file mode 100644 index 0000000..3052f39 --- /dev/null +++ b/vendor/librw/src/gles1/gl1render.cpp @@ -0,0 +1,138 @@ +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwrender.h" +#include "../rwengine.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#ifdef RW_GLES1 +#include "rwgles1.h" +#include "rwgles1impl.h" + +namespace rw { +namespace gles1 { + +#define MAX_LIGHTS + +void +drawInst_simple(InstanceDataHeader *header, InstanceData *inst) +{ + flushCache(); + glDrawElements(header->primType, inst->numIndex, + GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); +} + +void +drawInst(InstanceDataHeader *header, InstanceData *inst) +{ + drawInst_simple(header, inst); +} + + +void +setupVertexInput(InstanceDataHeader *header) +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); + glBindBuffer(GL_ARRAY_BUFFER, header->vbo); + bool hasNormal = false; + bool hasColor = false; + bool hasTex = false; + + for (int32 i = 0; i < header->numAttribs; i++) { + AttribDesc *a = &header->attribDesc[i]; + if (a->index == ATTRIB_POS) { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(a->size, a->type, a->stride, (void*)(uintptr)a->offset); + } else if (a->index == ATTRIB_NORMAL) { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(a->type, a->stride, (void*)(uintptr)a->offset); + hasNormal = true; + } else if (a->index == ATTRIB_COLOR){ + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(a->size, a->type, a->stride, (void*)(uintptr)a->offset); + hasColor = true; + } else if(a->index == ATTRIB_TEXCOORDS0){ + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(a->size, a->type, a->stride, (void*)(uintptr)a->offset); + hasTex = true; + } + } + if (!hasNormal) glDisableClientState(GL_NORMAL_ARRAY); + if (!hasColor) { + glDisableClientState(GL_COLOR_ARRAY); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } + if(!hasTex) glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void +teardownVertexInput(InstanceDataHeader *header) +{ +} + +int32 +lightingCB(Atomic *atomic) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 0; // 8; + lightData.locals = locals; + lightData.numLocals = 0; // 8; + + if(atomic->geometry->flags & rw::Geometry::LIGHT){ + ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData); + if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){ + // Get rid of lights that need normals when we don't have any + lightData.numDirectionals = 0; + lightData.numLocals = 0; + } + return setLights(&lightData); + }else{ + memset(&lightData, 0, sizeof(lightData)); + return setLights(&lightData); + } +} + +void +defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) +{ + Material *m; + + uint32 flags = atomic->geometry->flags; + setWorldMatrix(atomic->getFrame()->getLTM()); + //int32 vsBits = lightingCB(atomic); + + glDisable(GL_LIGHTING); + + setupVertexInput(header); + + InstanceData *inst = header->inst; + int32 n = header->numMeshes; + + while(n--){ + m = inst->material; + + setMaterial(flags, m->color, m->surfaceProps); + + setTexture(0, m->texture); + + rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF); + + drawInst(header, inst); + inst++; + } + teardownVertexInput(header); +} + + +} +} + +#endif + diff --git a/vendor/librw/src/gles1/gl1skin.cpp b/vendor/librw/src/gles1/gl1skin.cpp new file mode 100644 index 0000000..901923d --- /dev/null +++ b/vendor/librw/src/gles1/gl1skin.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwrender.h" +#include "../rwanim.h" +#include "../rwplugins.h" +#include "rwgles1.h" +#include "rwgles1plg.h" +#include "rwgles1impl.h" + +#ifdef RW_GLES1 + +namespace rw { +namespace gles1 { + +void +skinRenderCB(Atomic *atomic, InstanceDataHeader *header) +{ + Material *m; + uint32 flags = atomic->geometry->flags; + setWorldMatrix(atomic->getFrame()->getLTM()); + glDisable(GL_LIGHTING); + + setupVertexInput(header); + + InstanceData *inst = header->inst; + int32 n = header->numMeshes; + + while(n--){ + m = inst->material; + setMaterial(flags, m->color, m->surfaceProps); + setTexture(0, m->texture); + rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF); + drawInst(header, inst); + inst++; + } + + teardownVertexInput(header); +} + +// skinInstanceCB: igual que defaultInstanceCB, sin pesos/indices +// porque GLES1 no puede hacer skinning en GPU +void +skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance) +{ + defaultInstanceCB(geo, header, reinstance); +} + +void +skinUninstanceCB(Geometry *geo, InstanceDataHeader *header) +{ + assert(0 && "can't uninstance"); +} + +ObjPipeline* +makeSkinPipeline(void) +{ + ObjPipeline *pipe = ObjPipeline::create(); + pipe->instanceCB = skinInstanceCB; + pipe->uninstanceCB = skinUninstanceCB; + pipe->renderCB = skinRenderCB; + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + return pipe; +} + +static void* +skinOpen(void *o, int32, int32) +{ + skinGlobals.pipelines[PLATFORM_GLES1] = makeSkinPipeline(); + return o; +} + +static void* +skinClose(void *o, int32, int32) +{ + ((ObjPipeline*)skinGlobals.pipelines[PLATFORM_GLES1])->destroy(); + skinGlobals.pipelines[PLATFORM_GLES1] = nil; + return o; +} + +void +initSkin(void) +{ + Driver::registerPlugin(PLATFORM_GLES1, 0, ID_SKIN, skinOpen, skinClose); +} + +} +} + +#endif \ No newline at end of file diff --git a/vendor/librw/src/gles1/rwgles1.h b/vendor/librw/src/gles1/rwgles1.h new file mode 100644 index 0000000..0c15375 --- /dev/null +++ b/vendor/librw/src/gles1/rwgles1.h @@ -0,0 +1,255 @@ +#ifdef RW_GLES1 +#include +//#include +#include +#endif + +namespace rw { + +#ifdef RW_GLES1 +struct EngineOpenParams +{ + int width, height; + const char *windowtitle; +}; +#endif + +namespace gles1 { + +void registerPlatformPlugins(void); + +extern Device renderdevice; + +// arguments to glVertexAttribPointer basically +struct AttribDesc +{ + uint32 index; + int32 type; + bool32 normalized; + int32 size; + uint32 stride; + uint32 offset; +}; + +enum AttribIndices +{ + ATTRIB_POS = 0, + ATTRIB_NORMAL, + ATTRIB_COLOR, + ATTRIB_WEIGHTS, + ATTRIB_INDICES, + ATTRIB_TEXCOORDS0, + ATTRIB_TEXCOORDS1, +#if 0 + ATTRIB_TEXCOORDS2, + ATTRIB_TEXCOORDS3, + ATTRIB_TEXCOORDS4, + ATTRIB_TEXCOORDS5, + ATTRIB_TEXCOORDS6, + ATTRIB_TEXCOORDS7, +#endif +}; + +// default uniform indices +extern int32 u_matColor; +extern int32 u_surfProps; + +struct InstanceData +{ + uint32 numIndex; + uint32 minVert; // not used for rendering + int32 numVertices; // + Material *material; + bool32 vertexAlpha; + uint32 program; + uint32 offset; +}; + +struct InstanceDataHeader : rw::InstanceDataHeader +{ + uint32 serialNumber; + uint32 numMeshes; + uint16 *indexBuffer; + uint32 primType; + uint8 *vertexBuffer; + int32 numAttribs; + AttribDesc *attribDesc; + uint32 totalNumIndex; + uint32 totalNumVertex; + + uint32 ibo; + uint32 vbo; // or 2? + + InstanceData *inst; +}; + +#ifdef RW_GLES1 + +struct Im3DVertex +{ + V3d position; + uint8 r, g, b, a; + float32 u, v; + + void setX(float32 x) { this->position.x = x; } + void setY(float32 y) { this->position.y = y; } + void setZ(float32 z) { this->position.z = z; } + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { + this->r = r; this->g = g; this->b = b; this->a = a; } + void setU(float32 u) { this->u = u; } + void setV(float32 v) { this->v = v; } + + float getX(void) { return this->position.x; } + float getY(void) { return this->position.y; } + float getZ(void) { return this->position.z; } + RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); } + float getU(void) { return this->u; } + float getV(void) { return this->v; } +}; + +struct Im2DVertex +{ + float32 x, y, z, w; + uint8 r, g, b, a; + float32 u, v; + + void setScreenX(float32 x) { this->x = x; } + void setScreenY(float32 y) { this->y = y; } + void setScreenZ(float32 z) { this->z = z; } + // This is a bit unefficient but we have to counteract GL's divide, so multiply + void setCameraZ(float32 z) { this->w = z; } + void setRecipCameraZ(float32 recipz) { this->w = 1.0f/recipz; } + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { + this->r = r; this->g = g; this->b = b; this->a = a; } + void setU(float32 u, float recipz) { this->u = u; } + void setV(float32 v, float recipz) { this->v = v; } + + float getScreenX(void) { return this->x; } + float getScreenY(void) { return this->y; } + float getScreenZ(void) { return this->z; } + float getCameraZ(void) { return this->w; } + float getRecipCameraZ(void) { return 1.0f/this->w; } + RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); } + float getU(void) { return this->u; } + float getV(void) { return this->v; } +}; + +void setupVertexInput(InstanceDataHeader *header); +void teardownVertexInput(InstanceDataHeader *header); + +// Render state + +// Vertex shader bits +enum +{ + // These should be low so they could be used as indices + VSLIGHT_DIRECT = 1, + VSLIGHT_POINT = 2, + VSLIGHT_SPOT = 4, + VSLIGHT_MASK = 7, // all the above + // less critical + VSLIGHT_AMBIENT = 8, +}; +// per Scene +void setProjectionMatrix(float32*); +void setViewMatrix(float32*); + +// per Object +void setWorldMatrix(Matrix*); +int32 setLights(WorldLights *lightData); + +// per Mesh +void setTexture(int32 n, Texture *tex); +void setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f); +inline void setMaterial(uint32 flags, const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f) +{ + static RGBA white = { 255, 255, 255, 255 }; + if(flags & Geometry::MODULATE) + setMaterial(color, surfaceprops, extraSurfProp); + else + setMaterial(white, surfaceprops, extraSurfProp); +} + +void setAlphaBlend(bool32 enable); +bool32 getAlphaBlend(void); + +bool32 getAlphaTest(void); + +void bindFramebuffer(uint32 fbo); +uint32 bindTexture(uint32 texid); + +void flushCache(void); + +#endif + +class ObjPipeline : public rw::ObjPipeline +{ +public: + void init(void); + static ObjPipeline *create(void); + + void (*instanceCB)(Geometry *geo, InstanceDataHeader *header, bool32 reinstance); + void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header); + void (*renderCB)(Atomic *atomic, InstanceDataHeader *header); +}; + +void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance); +void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); +void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); +int32 lightingCB(Atomic *atomic); + +void drawInst_simple(InstanceDataHeader *header, InstanceData *inst); +// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer +void drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst); +// This one switches between the above two depending on render state; +void drawInst(InstanceDataHeader *header, InstanceData *inst); + + +void *destroyNativeData(void *object, int32, int32); + +ObjPipeline *makeDefaultPipeline(void); + +void setVertexAlpha(bool32 enable); + +// Native Texture and Raster + +struct Gl1Raster +{ + // arguments to glTexImage2D + int32 internalFormat; + int32 type; + int32 format; + int32 bpp; // bytes per pixel + // texture object + uint32 texid; + + bool isCompressed; + bool hasAlpha; + bool autogenMipmap; + int8 numLevels; + // cached filtermode and addressing + uint8 filterMode; + uint8 addressU; + uint8 addressV; + int32 maxAnisotropy; + + uint32 fbo; // used for camera texture only! + Raster *fboMate; // color or zbuffer raster mate of this one + RasterLevels *backingStore; // if we can't read back GPU memory but have to +}; + +// GLES can't read back textures very nicely. +// In most cases that's not an issue, but when it is, +// this has to be set before the texture is filled: +extern bool32 needToReadBackTextures; + +Texture *readNativeTexture(Stream *stream); +void writeNativeTexture(Texture *tex, Stream *stream); +uint32 getSizeNativeTexture(Texture *tex); + +extern int32 nativeRasterOffset; +void registerNativeRaster(void); +#define GETGL1RASTEREXT(raster) PLUGINOFFSET(Gl1Raster, raster, rw::gles1::nativeRasterOffset) + +} +} diff --git a/vendor/librw/src/gles1/rwgles1impl.h b/vendor/librw/src/gles1/rwgles1impl.h new file mode 100644 index 0000000..4164119 --- /dev/null +++ b/vendor/librw/src/gles1/rwgles1impl.h @@ -0,0 +1,83 @@ +namespace rw { +namespace gles1 { + +#ifdef RW_GLES1 + +extern uint32 im2DVbo, im2DIbo; +void openIm2D(void); +void closeIm2D(void); +void im2DRenderLine(void *vertices, int32 numVertices, + int32 vert1, int32 vert2); +void im2DRenderTriangle(void *vertices, int32 numVertices, + int32 vert1, int32 vert2, int32 vert3); +void im2DRenderPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices); +void im2DRenderIndexedPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices, void *indices, int32 numIndices); + +void openIm3D(void); +void closeIm3D(void); +void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags); +void im3DRenderPrimitive(PrimitiveType primType); +void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices); +void im3DEnd(void); + +struct DisplayMode +{ +#ifdef __SYMBIAN32__ + uint32 width; + uint32 height; +#else +#ifdef LIBRW_SDL2 + SDL_DisplayMode mode; +#else + GLFWvidmode mode; +#endif +#endif + int32 depth; + uint32 flags; +}; + +struct GlGlobals +{ +#ifdef LIBRW_SDL2 + SDL_Window **pWindow; + SDL_Window *window; + SDL_GLContext glcontext; +#else +#ifndef __SYMBIAN32__ + GLFWwindow **pWindow; + GLFWwindow *window; + + GLFWmonitor *monitor; +#endif + int numMonitors; + int currentMonitor; +#endif + + DisplayMode *modes; + int numModes; + int currentMode; + int presentWidth, presentHeight; + int presentOffX, presentOffY; + + // for opening the window + int winWidth, winHeight; + const char *winTitle; + uint32 numSamples; +}; + +extern GlGlobals glGlobals; +#endif + +Raster *rasterCreate(Raster *raster); +uint8 *rasterLock(Raster*, int32 level, int32 lockMode); +void rasterUnlock(Raster*, int32); +int32 rasterNumLevels(Raster*); +bool32 imageFindRasterFormat(Image *img, int32 type, + int32 *width, int32 *height, int32 *depth, int32 *format); +bool32 rasterFromImage(Raster *raster, Image *image); +Image *rasterToImage(Raster *raster); + +} +} diff --git a/vendor/librw/src/gles1/rwgles1plg.h b/vendor/librw/src/gles1/rwgles1plg.h new file mode 100644 index 0000000..8738929 --- /dev/null +++ b/vendor/librw/src/gles1/rwgles1plg.h @@ -0,0 +1,13 @@ +namespace rw { + namespace gles1 { + void initMatFX(void); + ObjPipeline *makeMatFXPipeline(void); + void matfxRenderCB(Atomic *atomic, InstanceDataHeader *header); + + void initSkin(void); + ObjPipeline *makeSkinPipeline(void); + void skinInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance); + void skinRenderCB(Atomic *atomic, InstanceDataHeader *header); + void uploadSkinMatrices(Atomic *atomic); + } +} \ No newline at end of file diff --git a/vendor/librw/src/image.cpp b/vendor/librw/src/image.cpp index c8cee64..b626399 100644 --- a/vendor/librw/src/image.cpp +++ b/vendor/librw/src/image.cpp @@ -413,9 +413,9 @@ flipAlphaBlock5_half(uint8 *dst, uint8 *src) dst[1] = src[1]; // bits uint64 bits = *(uint64*)&src[2]; - uint64 flipbits = bits & 0xFFFFFF000000; - flipbits |= (bits>>12) & 0xFFF; - flipbits |= (bits<<12) & 0xFFF000; + uint64 flipbits = bits & 0xFFFFFF000000ULL; + flipbits |= (bits>>12) & 0xFFFULL; + flipbits |= (bits<<12) & 0xFFF000ULL; memcpy(dst+2, &flipbits, 6); } diff --git a/vendor/librw/src/matfx.cpp b/vendor/librw/src/matfx.cpp index c143fc1..a7beefe 100644 --- a/vendor/librw/src/matfx.cpp +++ b/vendor/librw/src/matfx.cpp @@ -19,6 +19,8 @@ #include "gl/rwwdgl.h" #include "gl/rwgl3.h" #include "gl/rwgl3plg.h" +#include "gles1/rwgles1.h" +#include "gles1/rwgles1plg.h" #define PLUGIN_ID ID_MATFX @@ -619,6 +621,9 @@ registerMatFXPlugin(void) d3d9::initMatFX(); wdgl::initMatFX(); gl3::initMatFX(); +#ifdef RW_GLES1 + gles1::initMatFX(); +#endif matFXGlobals.atomicOffset = Atomic::registerPlugin(sizeof(int32), ID_MATFX, diff --git a/vendor/librw/src/rwbase.h b/vendor/librw/src/rwbase.h index e62325b..422de74 100644 --- a/vendor/librw/src/rwbase.h +++ b/vendor/librw/src/rwbase.h @@ -9,7 +9,13 @@ #endif #ifdef __SYMBIAN32__ +#undef stderr #define stderr stdout + #ifdef S60V5 + #define OFFSET_OF(type, member) ((size_t)&(((type*)0)->member)) + #else + #define OFFSET_OF offsetof + #endif #endif // TODO: clean up the opengl defines @@ -46,6 +52,11 @@ #define RW_OPENGL #endif +#ifdef RW_GLES1 +//#define RW_OPENGL +#define RWDEVICE gles1 +#endif + namespace rw { #ifdef RW_PS2 @@ -106,8 +117,9 @@ struct LLLink } }; + #define LLLinkGetData(linkvar,type,entry) \ - ((type*)(((rw::uint8*)(linkvar))-offsetof(type,entry))) + ((type*)(((rw::uint8*)(linkvar))-OFFSET_OF(type,entry))) // Have to be careful since the link might be deleted. #define FORLIST(_link, _list) \ @@ -546,6 +558,7 @@ enum Platform PLATFORM_WDGL = 11, // WarDrum OpenGL PLATFORM_GL3 = 12, // my GL3 implementation + PLATFORM_GLES1 = 13, NUM_PLATFORMS, @@ -619,6 +632,7 @@ enum PluginID ID_RASTERD3D9 = MAKEPLUGINID(VEND_RASTER, PLATFORM_D3D9), ID_RASTERWDGL = MAKEPLUGINID(VEND_RASTER, PLATFORM_WDGL), ID_RASTERGL3 = MAKEPLUGINID(VEND_RASTER, PLATFORM_GL3), + ID_RASTERGLES1 = MAKEPLUGINID(VEND_RASTER, PLATFORM_GLES1), // anything driver/device related (only as allocation tag) ID_DRIVER = MAKEPLUGINID(VEND_DRIVER, 0) diff --git a/vendor/librw/src/skin.cpp b/vendor/librw/src/skin.cpp index abaa548..3638d89 100644 --- a/vendor/librw/src/skin.cpp +++ b/vendor/librw/src/skin.cpp @@ -19,6 +19,8 @@ #include "gl/rwwdgl.h" #include "gl/rwgl3.h" #include "gl/rwgl3plg.h" +#include "gles1/rwgles1.h" +#include "gles1/rwgles1plg.h" #define PLUGIN_ID ID_SKIN @@ -373,7 +375,10 @@ registerSkinPlugin(void) d3d9::initSkin(); wdgl::initSkin(); gl3::initSkin(); - +#ifdef RW_GLES1 + gles1::initSkin(); +#endif + int32 o; o = Geometry::registerPlugin(sizeof(Skin*), ID_SKIN, createSkin, destroySkin, copySkin); diff --git a/vendor/librw/src/texture.cpp b/vendor/librw/src/texture.cpp index 958ae08..49baa52 100644 --- a/vendor/librw/src/texture.cpp +++ b/vendor/librw/src/texture.cpp @@ -17,6 +17,7 @@ #include "d3d/rwd3d9.h" #include "d3d/rwd3dimpl.h" #include "gl/rwgl3.h" +#include "gles1/rwgles1.h" #define PLUGIN_ID 0 @@ -481,6 +482,11 @@ Texture::streamReadNative(Stream *stream) return xbox::readNativeTexture(stream); if(platform == PLATFORM_GL3) return gl3::readNativeTexture(stream); +#ifdef RW_GLES1 + if(platform == PLATFORM_GLES1){ + return gles1::readNativeTexture(stream); + } +#endif assert(0 && "unsupported platform"); return nil; } @@ -498,6 +504,11 @@ Texture::streamWriteNative(Stream *stream) xbox::writeNativeTexture(this, stream); else if(this->raster->platform == PLATFORM_GL3) gl3::writeNativeTexture(this, stream); +#ifdef RW_GLES1 + else if(this->raster->platform == PLATFORM_GLES1){ + gles1::writeNativeTexture(this, stream); + } +#endif else assert(0 && "unsupported platform"); } @@ -515,6 +526,11 @@ Texture::streamGetSizeNative(void) return xbox::getSizeNativeTexture(this); if(this->raster->platform == PLATFORM_GL3) return gl3::getSizeNativeTexture(this); +#ifdef RW_GLES1 + if(this->raster->platform == PLATFORM_GLES1){ + return gles1::getSizeNativeTexture(this); + } +#endif assert(0 && "unsupported platform"); return 0; }