1 #ifndef H_CORE
2 #define H_CORE
3 
4 #ifdef _DEBUG
5     #define PROFILE
6 #endif
7 
8 #include <stdio.h>
9 #include <memory.h>
10 
11 #define OS_FILEIO_CACHE
12 #define OS_PTHREAD_MT
13 
14 #define USE_CUBEMAP_MIPS
15 
16 #ifdef __UWP__
17     #define _OS_UWP      1
18     #define _GAPI_D3D11  1
19 
20     #ifdef __XB1__
21         #define _OS_XB1
22     #endif
23 
24     #undef OS_PTHREAD_MT
25 #elif WIN32
26     #define _OS_WIN      1
27     #define _GAPI_GL     1
28     //#define _GAPI_D3D9   1
29     //#define _GAPI_D3D11  1
30     //#define _GAPI_VULKAN 1
31     //#define _GAPI_SW     1
32 
33     //#define _NAPI_SOCKET
34 
35     #include <windows.h>
36 
37     #undef OS_PTHREAD_MT
38 
39     #ifdef _GAPI_GL
40         #define VR_SUPPORT
41     #endif
42 #elif ANDROID
43     #define _OS_ANDROID 1
44     #define _GAPI_GL    1
45     #define _GAPI_GLES  1
46     //#define _GAPI_VULKAN
47 
48     #define VR_SUPPORT
49 #elif __SDL2__
50     #define _GAPI_GL   1
51     #ifdef SDL2_GLES
52         #define _GAPI_GLES 1
53         #define DYNGEOM_NO_VBO
54     #endif
55 #elif __RPI__
56     #define _OS_RPI    1
57     #define _GAPI_GL   1
58     #define _GAPI_GLES 1
59 
60     #define DYNGEOM_NO_VBO
61 #elif __CLOVER__
62     #define _OS_CLOVER 1
63     #define _GAPI_GL   1
64     #define _GAPI_GLES 1
65 
66     #define DYNGEOM_NO_VBO
67 #elif __PSC__
68     #define _OS_PSC    1
69     #define _GAPI_GL   1
70     #define _GAPI_GLES 1
71 
72     #define DYNGEOM_NO_VBO
73 #elif __BITTBOY__
74     #define _OS_BITTBOY 1
75     #define _OS_LINUX   1
76     #define _GAPI_SW    1
77 #elif __GCW0__
78     #define _OS_GCW0   1
79     #define _GAPI_GL   1
80     #define _GAPI_GLES 1
81 
82     #define DYNGEOM_NO_VBO
83 
84     // etnaviv driver has a bug with cubemap mips generator
85     #undef USE_CUBEMAP_MIPS
86 #elif __linux__
87     #define _OS_LINUX 1
88     #define _GAPI_GL  1
89 #elif __APPLE__
90     #define _GAPI_GL 1
91     #include "TargetConditionals.h"
92 
93     #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
94         #define _OS_IOS    1
95         #define _GAPI_GLES 1
96     #else
97         #define _OS_MAC    1
98     #endif
99 #elif __EMSCRIPTEN__
100     #define _OS_WEB    1
101     #define _GAPI_GL   1
102     #define _GAPI_GLES 1
103 
104     #undef  OS_FILEIO_CACHE
105 
106     extern int WEBGL_VERSION;
107 #elif _3DS
108     #include <3ds.h>
109 
110     #define _OS_3DS    1
111     #define _GAPI_C3D  1
112 
113     #undef OS_PTHREAD_MT
114     #undef USE_CUBEMAP_MIPS
115     #define USE_ATLAS_RGBA16
116 
117     // for 2352 stereo samples
118     // stb_vorbis - 8 ms
119     // libvorbis  - 6 ms
120     #define USE_LIBVORBIS
121 #elif _PSP
122     #define _OS_PSP  1
123     #define _GAPI_GU 1
124 
125     #define TEX_SWIZZLE
126     //#define EDRAM_MESH
127     #define EDRAM_TEX
128 
129     #undef OS_PTHREAD_MT
130 #elif __vita__
131     #define _OS_PSV   1
132     #define _GAPI_GXM 1
133 
134     #undef OS_PTHREAD_MT
135 #elif __SWITCH__
136     #define _OS_SWITCH 1
137     #define _GAPI_GL   1
138 
139     #undef OS_PTHREAD_MT
140 #elif _XBOX
141     #define _OS_XBOX   1
142     #define _GAPI_D3D8 1
143 
144     #undef OS_PTHREAD_MT
145     #undef USE_CUBEMAP_MIPS
146 
147     #define NOMINMAX
148     #include <xtl.h>
149     #include <xgraphics.h>
150 #elif _X360
151     #define _OS_X360  1
152     // TODO
153 #elif __NDLESS__
154     #define _OS_TNS   1
155     #define _GAPI_SW  1
156     #include <os.h>
157 
158     #undef OS_PTHREAD_MT
159 #endif
160 
161 #if !defined(_OS_PSP) && !defined(_OS_TNS)
162     #define USE_INFLATE
163 #endif
164 
165 #ifdef USE_INFLATE
166     #include "libs/tinf/tinf.h"
167 #endif
168 
169 #if defined(_GAPI_SW) || defined(_GAPI_GU)
170     #define FFP
171 #endif
172 
173 #ifdef FFP
174     #define SPLIT_BY_TILE
175     #if defined(_GAPI_GU)
176         #define SPLIT_BY_CLUT
177     #endif
178 #else
179     // current etnaviv driver implementation uses uncompatible Mesa GLSL compiler
180     // it produce unimplemented TRUNC/ARL instructions instead of F2I
181     // so we can't use joints indexing in the shader (see MESH_SKINNING)
182     #ifndef _OS_GCW0
183         #define MERGE_MODELS
184     #endif
185     #define MERGE_SPRITES
186     #define GENERATE_WATER_PLANE
187 #endif
188 
189 #include "utils.h"
190 
191 #if defined(_OS_3DS)
192     #define SHADOW_TEX_SIZE      512
193 #elif defined(_OS_GCW0)
194     #define SHADOW_TEX_SIZE      256
195 #elif defined(_OS_PSV)
196     #define SHADOW_TEX_SIZE      1024
197 #else
198     #define SHADOW_TEX_SIZE      2048
199 #endif
200 
201 extern void* osMutexInit     ();
202 extern void  osMutexFree     (void *obj);
203 extern void  osMutexLock     (void *obj);
204 extern void  osMutexUnlock   (void *obj);
205 
206 extern int   osGetTimeMS     ();
207 
208 extern bool  osJoyReady      (int index);
209 extern void  osJoyVibrate    (int index, float L, float R);
210 
211 #define OS_LOCK(mutex) Core::Lock _lock(mutex)
212 
213 enum InputKey { ikNone,
214 // keyboard
215     ikLeft, ikRight, ikUp, ikDown, ikSpace, ikTab, ikEnter, ikEscape, ikShift, ikCtrl, ikAlt,
216     ik0, ik1, ik2, ik3, ik4, ik5, ik6, ik7, ik8, ik9,
217     ikA, ikB, ikC, ikD, ikE, ikF, ikG, ikH, ikI, ikJ, ikK, ikL, ikM,
218     ikN, ikO, ikP, ikQ, ikR, ikS, ikT, ikU, ikV, ikW, ikX, ikY, ikZ,
219     ikN0, ikN1, ikN2, ikN3, ikN4, ikN5, ikN6, ikN7, ikN8, ikN9, ikNAdd, ikNSub, ikNMul, ikNDiv, ikNDot,
220     ikF1, ikF2, ikF3, ikF4, ikF5, ikF6, ikF7, ikF8, ikF9, ikF10, ikF11, ikF12,
221     ikMinus, ikPlus, ikLSB, ikRSB, ikSlash, ikBSlash, ikComma, ikDot, ikTilda, ikColon, ikApos, ikPrev, ikNext, ikHome, ikEnd, ikDel, ikIns, ikBack,
222 // mouse
223     ikMouseL, ikMouseR, ikMouseM,
224 // touch
225     ikTouchA, ikTouchB, ikTouchC, ikTouchD, ikTouchE, ikTouchF,
226 
227     ikMAX
228 };
229 
230 enum JoyKey {
231 // gamepad
232     jkNone, jkA, jkB, jkX, jkY, jkLB, jkRB, jkSelect, jkStart, jkL, jkR, jkLT, jkRT, jkLeft, jkRight, jkUp, jkDown, jkMAX
233 };
234 
235 enum ControlKey {
236     cLeft, cRight, cUp, cDown, cJump, cWalk, cAction, cWeapon, cLook, cDuck, cDash, cRoll, cInventory, cStart, cMAX
237 };
238 
239 struct KeySet {
240     uint8 key;
241     uint8 joy;
242 
KeySetKeySet243     KeySet() {}
KeySetKeySet244     KeySet(InputKey key, JoyKey joy) : key(key), joy(joy) {}
245 };
246 
247 enum RenderTargetOp {
248     RT_CLEAR_COLOR   = 0x0001,
249     RT_LOAD_COLOR    = 0x0002,
250     RT_STORE_COLOR   = 0x0004,
251 
252     RT_CLEAR_DEPTH   = 0x0008,
253     RT_LOAD_DEPTH    = 0x0010,
254     RT_STORE_DEPTH   = 0x0020,
255 };
256 
257 namespace Core {
258 
259     struct Mutex {
260         void *obj;
261 
MutexMutex262         Mutex()       { obj = osMutexInit(); }
~MutexMutex263         ~Mutex()      { osMutexFree(obj);    }
lockMutex264         void lock()   { osMutexLock(obj);    }
unlockMutex265         void unlock() { osMutexUnlock(obj);  }
266     };
267 
268     struct Lock {
269         Mutex &mutex;
270 
LockLock271         Lock(Mutex &mutex) : mutex(mutex) { mutex.lock(); }
~LockLock272         ~Lock() { mutex.unlock(); }
273     };
274 
275     float deltaTime;
276     int   lastTime;
277     int   x, y, width, height;
278 
279     struct Support {
280         int  maxVectors;
281         int  maxAniso;
282         int  texMinSize;
283         bool shaderBinary;
284         bool VAO;
285         bool VBO;
286         bool depthTexture;
287         bool shadowSampler;
288         bool discardFrame;
289         bool derivatives;
290         bool texNPOT;
291         bool tex3D;
292         bool texRG;
293         bool texBorder;
294         bool texMaxLevel;
295         bool colorFloat, texFloat, texFloatLinear;
296         bool colorHalf, texHalf,  texHalfLinear;
297     #ifdef PROFILE
298         bool profMarker;
299         bool profTiming;
300     #endif
301     } support;
302 
303 #define SETTINGS_VERSION 7
304 #define SETTINGS_READING 0xFF
305 
306     struct Settings {
307         enum Quality  { LOW, MEDIUM, HIGH };
308         enum Stereo   { STEREO_OFF, STEREO_SBS, STEREO_ANAGLYPH, STEREO_SPLIT, STEREO_VR };
309         enum Scale    { SCALE_25, SCALE_50, SCALE_75, SCALE_100 };
310 
311         uint8 version;
312 
313         struct {
314             union {
315                 struct {
316                     uint8 filter;
317                     uint8 lighting;
318                     uint8 shadows;
319                     uint8 water;
320                 };
321                 uint8 quality[4];
322             };
323             uint8 simple;
324             uint8 scale;
325             uint8 vsync;
326             uint8 stereo;
setFilterSettings::__anon6c24faa50108327             void setFilter(Quality value) {
328                 if (value > MEDIUM && !(support.maxAniso > 1))
329                     value = MEDIUM;
330                 filter = value;
331             }
332 
setLightingSettings::__anon6c24faa50108333             void setLighting(Quality value) {
334             #if defined(_GAPI_SW) || defined(_GAPI_GU)
335                 lighting = LOW;
336             #else
337                 lighting = value;
338             #endif
339             }
340 
setShadowsSettings::__anon6c24faa50108341             void setShadows(Quality value) {
342             #if defined(_GAPI_SW) || defined(_GAPI_GU)
343                 shadows = LOW;
344             #else
345                 shadows = value;
346             #endif
347             }
348 
setWaterSettings::__anon6c24faa50108349             void setWater(Quality value) {
350             #if defined(_GAPI_SW) || defined(_GAPI_GU)
351                 water = LOW;
352             #else
353                 if (value > LOW && !(support.texFloat || support.texHalf))
354                     value = LOW;
355                 if (value > MEDIUM && !support.derivatives)
356                     value = MEDIUM;
357                 water = value;
358             #endif
359             }
360 
isStereoSettings::__anon6c24faa50108361             bool isStereo() {
362                 return stereo == STEREO_SBS || stereo == STEREO_ANAGLYPH || stereo == STEREO_VR;
363             }
364         } detail;
365 
366         struct {
367             uint8 music;
368             uint8 sound;
369             uint8 reverb;
370             uint8 subtitles;
371             uint8 language;
372         } audio;
373 
374         struct Controls {
375             uint8  joyIndex;
376             uint8  vibration;
377             uint8  retarget;
378             uint8  multiaim;
379             KeySet keys[cMAX];
380         } controls[2];
381 
382         // temporary, used only for setting controls
383         uint8 playerIndex;
384         uint8 ctrlIndex;
385     } settings;
386 
387     bool resetState;
388     bool isQuit;
389 
getTime()390     int getTime() {
391         return osGetTimeMS();
392     }
393 
resetTime()394     void resetTime() {
395         lastTime = getTime();
396         resetState = true;
397     }
398 
quit()399     void quit() {
400         isQuit = true;
401     }
402 }
403 
404 #ifdef VR_SUPPORT
405 extern void osToggleVR(bool enable);
406 #else
osToggleVR(bool enable)407 void osToggleVR(bool enable) {
408     Core::settings.detail.stereo = Core::Settings::STEREO_OFF;
409 }
410 #endif
411 
412 #ifdef PROFILE
413     struct TimingCPU {
414         int &result;
415 
TimingCPUTimingCPU416         TimingCPU(int &result) : result(result) {
417             result = Core::getTime();
418         }
419 
~TimingCPUTimingCPU420         ~TimingCPU() {
421             result = Core::getTime() - result;
422         }
423     };
424 
425     #define PROFILE_CPU_TIMING(result)  TimingCPU timingCPU(result)
426 #else
427     #define PROFILE_CPU_TIMING(result)
428 #endif
429 
430 #include "input.h"
431 #include "sound.h"
432 
433 #if defined(_NAPI_SOCKET)
434     #include "napi_socket.h"
435 #else
436     #include "napi_dummy.h"
437 #endif
438 
439 #define LIGHT_STACK_SIZE     1
440 #define MAX_LIGHTS           4
441 #define MAX_RENDER_BUFFERS   32
442 #define MAX_CONTACTS         15
443 #define NOISE_TEX_SIZE       32
444 #define PERLIN_TEX_SIZE      128
445 #define PERLIN_TEX_NAME      "perlin3_128.raw"
446 
447 struct Shader;
448 struct Texture;
449 
450 namespace GAPI {
451     struct Shader;
452     struct Texture;
453 }
454 
455 enum RenderState {
456     RS_TARGET           = 1 << 0,
457     RS_VIEWPORT         = 1 << 1,
458     RS_SCISSOR          = 1 << 2,
459     RS_DEPTH_TEST       = 1 << 3,
460     RS_DEPTH_WRITE      = 1 << 4,
461     RS_COLOR_WRITE_R    = 1 << 5,
462     RS_COLOR_WRITE_G    = 1 << 6,
463     RS_COLOR_WRITE_B    = 1 << 7,
464     RS_COLOR_WRITE_A    = 1 << 8,
465     RS_COLOR_WRITE      = RS_COLOR_WRITE_R | RS_COLOR_WRITE_G | RS_COLOR_WRITE_B | RS_COLOR_WRITE_A,
466     RS_CULL_BACK        = 1 << 9,
467     RS_CULL_FRONT       = 1 << 10,
468     RS_CULL             = RS_CULL_BACK | RS_CULL_FRONT,
469     RS_BLEND_ALPHA      = 1 << 11,
470     RS_BLEND_ADD        = 1 << 12,
471     RS_BLEND_MULT       = 1 << 13,
472     RS_BLEND_PREMULT    = 1 << 14,
473     RS_BLEND            = RS_BLEND_ALPHA | RS_BLEND_ADD | RS_BLEND_MULT | RS_BLEND_PREMULT,
474     RS_DISCARD          = 1 << 15,
475 };
476 
477 // Texture image format
478 enum TexFormat {
479     FMT_LUMINANCE,
480     FMT_RGBA,
481     FMT_RGB16,
482     FMT_RGBA16,
483     FMT_RG_FLOAT,
484     FMT_RG_HALF,
485     FMT_DEPTH,
486     FMT_SHADOW,
487     FMT_MAX,
488 };
489 
490 // Texture options
491 enum TexOption {
492     OPT_REPEAT      = 0x0001,
493     OPT_CUBEMAP     = 0x0002,
494     OPT_VOLUME      = 0x0004,
495     OPT_MIPMAPS     = 0x0008,
496     OPT_NEAREST     = 0x0010,
497     OPT_TARGET      = 0x0020,
498     OPT_VERTEX      = 0x0040,
499     OPT_DYNAMIC     = 0x0080,
500     OPT_DEPEND      = 0x0100,
501     OPT_PROXY       = 0x0200,
502     OPT_VRAM_3DS    = 0x0400,
503 };
504 
505 // Pipeline State Object
506 struct PSO {
507     void       *data;
508     void       *shader;
509     vec4       clearColor;
510     TexFormat  colorFormat;
511     TexFormat  depthFormat;
512     uint32     renderState;
513 };
514 
515 #if !defined(FFP) && (defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_MAC) || defined(_OS_WEB))
516     typedef uint32 Index;
517 #else
518     typedef uint16 Index;
519 #endif
520 
521 struct Edge {
522     Index a, b;
523 
EdgeEdge524     Edge() {}
EdgeEdge525     Edge(Index a, Index b) : a(a), b(b) {}
526 };
527 
528 struct Vertex {
529     short4 coord;      // xyz  - position, w - joint index (for entities only)
530     short4 normal;     // xyz  - vertex normal, w - quad(0) or triangle (1)
531     short4 texCoord;   // xy   - texture coordinates, zw - trapezoid warping
532     ubyte4 color;      // for non-textured geometry
533     ubyte4 light;      // xyz  - color, w - use premultiplied alpha
534 };
535 
536 struct MeshRange {
537     int iStart;
538     int iCount;
539     int vStart;
540     int aIndex;
541 
542     uint16 tile;
543     uint16 clut;
544 
MeshRangeMeshRange545     MeshRange() : iStart(0), iCount(0), vStart(0), aIndex(-1), tile(0), clut(0) {}
546 };
547 
548 #define SHADER_ATTRIBS(E) \
549     E( aCoord           ) \
550     E( aNormal          ) \
551     E( aTexCoord        ) \
552     E( aColor           ) \
553     E( aLight           )
554 
555 #define SHADER_SAMPLERS(E) \
556     E( sDiffuse         ) \
557     E( sNormal          ) \
558     E( sReflect         ) \
559     E( sShadow          ) \
560     E( sMask            )
561 
562 #define SHADER_UNIFORMS(E) \
563     E( uParam           ) \
564     E( uTexParam        ) \
565     E( uViewProj        ) \
566     E( uBasis           ) \
567     E( uLightProj       ) \
568     E( uMaterial        ) \
569     E( uAmbient         ) \
570     E( uFogParams       ) \
571     E( uViewPos         ) \
572     E( uLightPos        ) \
573     E( uLightColor      ) \
574     E( uRoomSize        ) \
575     E( uPosScale        ) \
576     E( uContacts        )
577 
578 #define SHADER_DEFINES(E) \
579     /* shadow types */ \
580     E( SHADOW_SAMPLER ) \
581     E( SHADOW_DEPTH   ) \
582     E( SHADOW_COLOR   ) \
583     /* compose types */ \
584     E( TYPE_SPRITE    ) \
585     E( TYPE_FLASH     ) \
586     E( TYPE_ROOM      ) \
587     E( TYPE_ENTITY    ) \
588     E( TYPE_MIRROR    ) \
589     /* sky */ \
590     E( SKY_TEXTURE      ) \
591     E( SKY_CLOUDS       ) \
592     E( SKY_CLOUDS_AZURE ) \
593     /* water sub-passes */ \
594     E( WATER_DROP     ) \
595     E( WATER_SIMULATE ) \
596     E( WATER_CAUSTICS ) \
597     E( WATER_RAYS     ) \
598     E( WATER_MASK     ) \
599     E( WATER_COMPOSE  ) \
600     /* filter types */ \
601     E( FILTER_UPSCALE          ) \
602     E( FILTER_DOWNSAMPLE       ) \
603     E( FILTER_DOWNSAMPLE_DEPTH ) \
604     E( FILTER_GRAYSCALE        ) \
605     E( FILTER_BLUR             ) \
606     E( FILTER_ANAGLYPH         ) \
607     E( FILTER_EQUIRECTANGULAR  ) \
608     /* options */ \
609     E( UNDERWATER      ) \
610     E( ALPHA_TEST      ) \
611     E( OPT_AMBIENT     ) \
612     E( OPT_SHADOW      ) \
613     E( OPT_CONTACT     ) \
614     E( OPT_CAUSTICS    )
615 
616 enum AttribType   { SHADER_ATTRIBS(DECL_ENUM)  aMAX };
617 enum SamplerType  { SHADER_SAMPLERS(DECL_ENUM) sMAX };
618 enum UniformType  { SHADER_UNIFORMS(DECL_ENUM) uMAX };
619 
620 #define DECL_SD_ENUM(v) SD_##v,
621 enum ShaderDefine { SHADER_DEFINES(DECL_SD_ENUM) SD_MAX };
622 #undef DECL_SD_ENUM
623 
624 const char *AttribName[aMAX]  = { SHADER_ATTRIBS(DECL_STR)  };
625 const char *SamplerName[sMAX] = { SHADER_SAMPLERS(DECL_STR) };
626 const char *UniformName[uMAX] = { SHADER_UNIFORMS(DECL_STR) };
627 
628 #undef SHADER_ATTRIBS
629 #undef SHADER_SAMPLERS
630 #undef SHADER_UNIFORMS
631 
632 enum CullMode  { cmNone, cmBack,  cmFront, cmMAX };
633 enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult, bmMAX };
634 
635 namespace Core {
636     float eye;
637     float aspectFix = 1.0f;
638     Texture *eyeTex[2];
639     short4 viewport, viewportDef, scissor;
640     mat4 mModel, mView, mProj, mViewProj, mViewInv;
641     mat4 mLightProj;
642     Basis basis;
643     vec4 viewPos;
644     vec4 lightPos[MAX_LIGHTS];
645     vec4 lightColor[MAX_LIGHTS];
646     vec4 params;
647     vec4 contacts[MAX_CONTACTS];
648 
649     struct LightStack {
650         vec4 pos[MAX_LIGHTS];
651         vec4 color[MAX_LIGHTS];
652     } lightStack[LIGHT_STACK_SIZE];
653     int lightStackCount;
654 
655     Texture *whiteTex, *whiteCube, *blackTex, *ditherTex, *noiseTex, *perlinTex;
656 
657     enum Pass { passCompose, passShadow, passAmbient, passSky, passWater, passFilter, passGUI, passMAX } pass;
658 
659     GAPI::Texture *defaultTarget;
660 
661     int32   renderState;
662 
663     struct Active {
664         const PSO     *pso;
665         GAPI::Shader  *shader;
666         GAPI::Texture *textures[8];
667         GAPI::Texture *target;
668         int32         renderState;
669         uint32        targetFace;
670         uint32        targetOp;
671         short4        viewport; // x, y, width, height
672         short4        scissor;  // x, y, width, height
673         vec4          material;
674 
675     #ifdef _GAPI_GL
676         uint32 VAO;
677         uint32 iBuffer;
678         uint32 vBuffer;
679     #endif
680 
681     #ifdef _GAPI_GXM
682         Vertex *vBuffer;
683     #endif
684 
685     #ifdef _GAPI_C3D
686         void *VAO;
687     #endif
688 
689         int32       basisCount;
690         Basis       *basis;
691     } active;
692 
693     struct ReqTarget {
694         GAPI::Texture *texture;
695         uint32  op;
696         uint32  face;
697     } reqTarget;
698 
699     struct Stats {
700         uint32 dips, tris, rt, cb, frame, frameIndex, fps;
701         int fpsTime;
702     #ifdef PROFILE
703         int tFrame;
704         int video;
705     #endif
706 
StatsStats707         Stats() : frame(0), frameIndex(0), fps(0), fpsTime(0) {}
708 
startStats709         void start() {
710             dips = tris = rt = cb = 0;
711         }
712 
stopStats713         void stop() {
714             if (fpsTime < Core::getTime()) {
715                 LOG("FPS: %d DIP: %d TRI: %d RT: %d\n", fps, dips, tris, rt);
716             #ifdef PROFILE
717                 LOG("frame time: %d mcs\n", tFrame / 1000);
718                 LOG("sound: mix %d rev %d ren %d/%d ogg %d\n", Sound::stats.mixer, Sound::stats.reverb, Sound::stats.render[0], Sound::stats.render[1], Sound::stats.ogg);
719                 LOG("video: %d\n", video);
720             #endif
721                 fps     = frame;
722                 frame   = 0;
723                 fpsTime = Core::getTime() + 1000;
724             } else
725                 frame++;
726 
727             frameIndex++;
728         }
729     } stats;
730 }
731 
732 #ifdef _GAPI_SW
733     #include "gapi/sw.h"
734 #elif _GAPI_GL
735     #include "gapi/gl.h"
736 #elif _GAPI_D3D8
737     #include "gapi/d3d8.h"
738 #elif _GAPI_D3D9
739     #include "gapi/d3d9.h"
740 #elif _GAPI_D3D11
741     #include "gapi/d3d11.h"
742 #elif _OS_3DS
743     #include "gapi/c3d.h"
744 #elif _GAPI_GU
745     #include "gapi/gu.h"
746 #elif _GAPI_GXM
747     #include "gapi/gxm.h"
748 #elif _GAPI_VULKAN
749     #include "gapi/vk.h"
750 #endif
751 
752 #include "texture.h"
753 #include "shader.h"
754 #include "video.h"
755 
756 namespace Core {
757 
758     static const char *version = __DATE__;
759     static int defLang = 0;
760 
readPerlinAsync(Stream * stream,void * userData)761     void readPerlinAsync(Stream *stream, void *userData) {
762         int size = PERLIN_TEX_SIZE * PERLIN_TEX_SIZE * PERLIN_TEX_SIZE;
763         uint8 *perlinData = NULL;
764 
765         if (stream && stream->size == size) {
766             perlinData = new uint8[size];
767             stream->raw(perlinData, size);
768         } else {
769             perlinData = Noise::generate(123456, PERLIN_TEX_SIZE, 5, 8, 1.0f);
770             Stream::cacheWrite(PERLIN_TEX_NAME, (char*)perlinData, size);
771         }
772         delete stream;
773 
774         perlinTex = new Texture(PERLIN_TEX_SIZE, PERLIN_TEX_SIZE, PERLIN_TEX_SIZE, FMT_LUMINANCE, OPT_REPEAT | OPT_VOLUME, perlinData);
775     /*/
776         uint8 *pdata = new uint8[SQR(PERLIN_TEX_SIZE) * 4];
777         int offset = 0;
778         for (int k = 0; k < PERLIN_TEX_SIZE; k++) {
779             int j = 0;
780             for (int i = 0; i < SQR(PERLIN_TEX_SIZE); i++) {
781                 pdata[j + 0] = pdata[j + 1] = pdata[j + 2] = perlinData[offset + i];
782                 pdata[j + 3] = 255;
783                 j += 4;
784             }
785             char buf[256];
786             sprintf(buf, "noise/perlin_%03d", k);
787             Texture::SaveBMP(buf, (char*)pdata, PERLIN_TEX_SIZE, PERLIN_TEX_SIZE);
788             offset += PERLIN_TEX_SIZE * PERLIN_TEX_SIZE;
789         }
790         delete[] pdata;
791     */
792         delete[] perlinData;
793     }
794 
init()795     void init() {
796         LOG("OpenLara (%s)\n", version);
797 
798         x = y = 0;
799         eyeTex[0] = eyeTex[1] = NULL;
800         lightStackCount = 0;
801 
802         memset(&support, 0, sizeof(support));
803         support.texMinSize  = 1;
804         support.texMaxLevel = true;
805         support.derivatives = true;
806 
807         #ifdef USE_INFLATE
808             tinf_init();
809         #endif
810 
811         isQuit = false;
812 
813         Input::init();
814         Sound::init();
815         NAPI::init();
816 
817         GAPI::init();
818 
819         #ifdef _OS_3DS
820             Core::eyeTex[0] = new Texture(Core::width, Core::height, 1, TexFormat::FMT_RGB16, OPT_TARGET | OPT_PROXY);
821             Core::eyeTex[1] = new Texture(Core::width, Core::height, 1, TexFormat::FMT_RGB16, OPT_TARGET | OPT_PROXY);
822             GAPI::Texture *outputTex[2] = { Core::eyeTex[0], Core::eyeTex[1] };
823             GAPI::initOutput(outputTex);
824         #endif
825 
826         LOG("cache    : %s\n", cacheDir);
827         LOG("supports :\n");
828         LOG("  variyngs count : %d\n", support.maxVectors);
829         LOG("  binary shaders : %s\n", support.shaderBinary  ? "true" : "false");
830         LOG("  vertex arrays  : %s\n", support.VAO           ? "true" : "false");
831         LOG("  depth texture  : %s\n", support.depthTexture  ? "true" : "false");
832         LOG("  shadow sampler : %s\n", support.shadowSampler ? "true" : "false");
833         LOG("  discard frame  : %s\n", support.discardFrame  ? "true" : "false");
834         LOG("  NPOT textures  : %s\n", support.texNPOT       ? "true" : "false");
835         LOG("  3D   textures  : %s\n", support.tex3D         ? "true" : "false");
836         LOG("  RG   textures  : %s\n", support.texRG         ? "true" : "false");
837         LOG("  border color   : %s\n", support.texBorder     ? "true" : "false");
838         LOG("  max level      : %s\n", support.texMaxLevel   ? "true" : "false");
839         LOG("  anisotropic    : %d\n", support.maxAniso);
840         LOG("  float textures : float = %s, half = %s\n",
841             support.colorFloat ? "full" : (support.texFloat ? (support.texFloatLinear ? "linear" : "nearest") : "false"),
842             support.colorHalf  ? "full" : (support.texHalf  ? (support.texHalfLinear  ? "linear" : "nearest") : "false"));
843         LOG("\n");
844 
845         defaultTarget = NULL;
846 
847         for (int i = 0; i < MAX_LIGHTS; i++) {
848             lightPos[i]   = vec3(0.0);
849             lightColor[i] = vec4(0, 0, 0, 1);
850         }
851         eye = 0.0f;
852 
853         { // init dummy textures
854             int size = SQR(support.texMinSize) * 6;
855             uint32 *data = new uint32[size];
856             memset(data, 0xFF, size * sizeof(data[0]));
857             whiteTex  = new Texture(support.texMinSize, support.texMinSize, 1, FMT_RGBA, OPT_NEAREST, data);
858             whiteCube = new Texture(support.texMinSize, support.texMinSize, 1, FMT_RGBA, OPT_CUBEMAP, data);
859             memset(data, 0x00, size * sizeof(data[0]));
860             blackTex  = new Texture(support.texMinSize, support.texMinSize, 1, FMT_RGBA, OPT_NEAREST, data);
861             delete[] data;
862         }
863 
864         { // generate dithering texture
865             uint8 ditherData[] = {
866                 0x00, 0x7F, 0x1F, 0x9F, 0x07, 0x87, 0x27, 0xA7,
867                 0xBF, 0x3F, 0xDF, 0x5F, 0xC7, 0x47, 0xE7, 0x67,
868                 0x2F, 0xAF, 0x0F, 0x8F, 0x37, 0xB7, 0x17, 0x97,
869                 0xEF, 0x6F, 0xCF, 0x4F, 0xF7, 0x77, 0xD7, 0x57,
870                 0x0B, 0x8B, 0x2B, 0xAB, 0x03, 0x83, 0x23, 0xA3,
871                 0xCB, 0x4B, 0xEB, 0x6B, 0xC3, 0x43, 0xE3, 0x63,
872                 0x3B, 0xBB, 0x1B, 0x9B, 0x33, 0xB3, 0x13, 0x93,
873                 0xFB, 0x7B, 0xDB, 0x5B, 0xF3, 0x73, 0xD3, 0x53,
874             };
875             ditherTex = new Texture(8, 8, 1, FMT_LUMINANCE, OPT_REPEAT | OPT_NEAREST, &ditherData);
876         }
877 
878         { // generate noise texture
879             uint8 *noiseData = new uint8[SQR(NOISE_TEX_SIZE) * 4];
880             for (int i = 0; i < SQR(NOISE_TEX_SIZE) * 4; i++) {
881                 noiseData[i] = rand() % 255;
882             }
883             noiseTex = new Texture(NOISE_TEX_SIZE, NOISE_TEX_SIZE, 1, FMT_RGBA, OPT_REPEAT, noiseData);
884             delete[] noiseData;
885         }
886 
887         perlinTex = NULL;
888         if (support.tex3D) {
889             Stream::cacheRead(PERLIN_TEX_NAME, readPerlinAsync);
890         }
891 
892     // init settings
893         settings.version = SETTINGS_VERSION;
894 
895         settings.detail.setFilter   (Core::Settings::HIGH);
896         settings.detail.setLighting (Core::Settings::HIGH);
897         settings.detail.setShadows  (Core::Settings::HIGH);
898         settings.detail.setWater    (Core::Settings::HIGH);
899         settings.detail.simple       = false;
900         settings.detail.vsync        = true;
901         settings.detail.stereo       = Settings::STEREO_OFF;
902         settings.detail.scale        = Settings::SCALE_100;
903         settings.audio.music         = SND_MAX_VOLUME;
904         settings.audio.sound         = SND_MAX_VOLUME;
905         settings.audio.reverb        = true;
906         settings.audio.subtitles     = true;
907         settings.audio.language      = defLang;
908 
909     // player 1
910         {
911             Settings::Controls &ctrl = settings.controls[0];
912             ctrl.joyIndex  = 0;
913             ctrl.vibration = true;
914             ctrl.retarget  = true;
915             ctrl.multiaim  = true;
916 
917             ctrl.keys[ cLeft      ] = KeySet( ikLeft,   jkLeft   );
918             ctrl.keys[ cRight     ] = KeySet( ikRight,  jkRight  );
919             ctrl.keys[ cUp        ] = KeySet( ikUp,     jkUp     );
920             ctrl.keys[ cDown      ] = KeySet( ikDown,   jkDown   );
921             ctrl.keys[ cJump      ] = KeySet( ikAlt,    jkX      );
922             ctrl.keys[ cWalk      ] = KeySet( ikShift,  jkRB     );
923             ctrl.keys[ cAction    ] = KeySet( ikCtrl,   jkA      );
924             ctrl.keys[ cWeapon    ] = KeySet( ikSpace,  jkY      );
925             ctrl.keys[ cLook      ] = KeySet( ikC,      jkLB     );
926             ctrl.keys[ cDuck      ] = KeySet( ikZ,      jkLT     );
927             ctrl.keys[ cDash      ] = KeySet( ikX,      jkRT     );
928             ctrl.keys[ cRoll      ] = KeySet( ikA,      jkB      );
929             ctrl.keys[ cInventory ] = KeySet( ikEscape, jkSelect );
930             ctrl.keys[ cStart     ] = KeySet( ikEnter,  jkStart  );
931         }
932 
933     // player 2
934         {
935             Settings::Controls &ctrl = settings.controls[1];
936             ctrl.joyIndex  = 1;
937             ctrl.vibration = true;
938             ctrl.retarget  = true;
939             ctrl.multiaim  = true;
940 
941             ctrl.keys[ cLeft      ] = KeySet( ikNone,   jkLeft   );
942             ctrl.keys[ cRight     ] = KeySet( ikNone,   jkRight  );
943             ctrl.keys[ cUp        ] = KeySet( ikNone,   jkUp     );
944             ctrl.keys[ cDown      ] = KeySet( ikNone,   jkDown   );
945             ctrl.keys[ cJump      ] = KeySet( ikNone,   jkX      );
946             ctrl.keys[ cWalk      ] = KeySet( ikNone,   jkRB     );
947             ctrl.keys[ cAction    ] = KeySet( ikNone,   jkA      );
948             ctrl.keys[ cWeapon    ] = KeySet( ikNone,   jkY      );
949             ctrl.keys[ cLook      ] = KeySet( ikNone,   jkLB     );
950             ctrl.keys[ cDuck      ] = KeySet( ikNone,   jkLT     );
951             ctrl.keys[ cDash      ] = KeySet( ikNone,   jkRT     );
952             ctrl.keys[ cRoll      ] = KeySet( ikNone,   jkB      );
953             ctrl.keys[ cInventory ] = KeySet( ikNone,   jkSelect );
954             ctrl.keys[ cStart     ] = KeySet( ikNone,   jkStart  );
955         }
956 
957     // use S key for action on Mac because Ctrl + Left/Right used by system (default)
958     #ifdef _OS_MAC
959         settings.controls[0].keys[ cAction    ].key = ikS;
960     #endif
961 
962     // use D key for jump in browsers
963     #ifdef _OS_WEB
964         settings.controls[0].keys[ cJump      ].key = ikD;
965         settings.controls[0].keys[ cInventory ].key = ikTab;
966 
967         settings.audio.music = 14;
968         settings.audio.sound = 14;
969     #endif
970 
971     #if defined(_OS_RPI) || defined(_OS_CLOVER)
972         settings.detail.setShadows  (Core::Settings::LOW);
973         settings.detail.setLighting (Core::Settings::MEDIUM);
974     #endif
975 
976     #if defined(_OS_GCW0)
977         settings.detail.setFilter   (Core::Settings::MEDIUM);
978         settings.detail.setShadows  (Core::Settings::MEDIUM);
979         settings.detail.setLighting (Core::Settings::MEDIUM);
980         settings.audio.subtitles = false;
981     #endif
982 
983     #ifdef _OS_PSC
984         settings.detail.setLighting (Core::Settings::MEDIUM);
985         settings.detail.setShadows  (Core::Settings::LOW);
986         settings.detail.setWater    (Core::Settings::LOW);
987     #endif
988 
989     #ifdef _OS_3DS
990         settings.detail.setFilter   (Core::Settings::MEDIUM);
991         settings.detail.setLighting (Core::Settings::LOW);
992         settings.detail.setShadows  (Core::Settings::LOW);
993         settings.detail.setWater    (Core::Settings::LOW);
994 
995         settings.audio.reverb = false;
996     #endif
997 
998     #ifdef FFP
999         settings.detail.setFilter   (Core::Settings::MEDIUM);
1000         settings.detail.setLighting (Core::Settings::LOW);
1001         settings.detail.setShadows  (Core::Settings::LOW);
1002         settings.detail.setWater    (Core::Settings::LOW);
1003     #endif
1004 
1005     #ifdef _OS_PSP
1006         settings.audio.reverb = false;
1007     #endif
1008 
1009     #ifdef _OS_PSV
1010         settings.detail.setFilter   (Core::Settings::HIGH);
1011         settings.detail.setLighting (Core::Settings::LOW);
1012         settings.detail.setShadows  (Core::Settings::LOW);
1013         settings.detail.setWater    (Core::Settings::MEDIUM);
1014     #endif
1015 
1016     #ifdef _OS_XBOX
1017         settings.detail.setFilter   (Core::Settings::HIGH);
1018         settings.detail.setLighting (Core::Settings::LOW);
1019         settings.detail.setShadows  (Core::Settings::LOW);
1020         settings.detail.setWater    (Core::Settings::LOW);
1021     #endif
1022 
1023         memset(&active, 0, sizeof(active));
1024         renderState = 0;
1025 
1026         resetTime();
1027     }
1028 
deinit()1029     void deinit() {
1030         delete eyeTex[0];
1031         delete eyeTex[1];
1032         delete whiteTex;
1033         delete whiteCube;
1034         delete blackTex;
1035         delete ditherTex;
1036         delete noiseTex;
1037         delete perlinTex;
1038 
1039         GAPI::deinit();
1040         NAPI::deinit();
1041         Sound::deinit();
1042         Stream::deinit();
1043     }
1044 
setVSync(bool enable)1045     void setVSync(bool enable) {
1046         GAPI::setVSync((Core::settings.detail.vsync = enable));
1047     }
1048 
waitVBlank()1049     void waitVBlank() {
1050         if (Core::settings.detail.vsync)
1051             GAPI::waitVBlank();
1052     }
1053 
update()1054     bool update() {
1055         resetState = false;
1056         int time = getTime();
1057         if (time - lastTime <= 0)
1058             return false;
1059         deltaTime = (time - lastTime) * 0.001f;
1060         lastTime = time;
1061         return true;
1062     }
1063 
validateRenderState()1064     void validateRenderState() {
1065         int32 mask = renderState ^ active.renderState;
1066         if (!mask) return;
1067 
1068         if (mask & RS_TARGET) {
1069             GAPI::discardTarget(!(active.targetOp & RT_STORE_COLOR), !(active.targetOp & RT_STORE_DEPTH));
1070 
1071             GAPI::Texture *target = reqTarget.texture;
1072             uint32  face          = reqTarget.face;
1073 
1074             if (target != active.target || face != active.targetFace) {
1075                 Core::stats.rt++;
1076 
1077                 GAPI::bindTarget(target, face);
1078 
1079                 bool depth = target && (target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW);
1080                 if (support.discardFrame) {
1081                     if (!(reqTarget.op & RT_LOAD_COLOR) && !depth) reqTarget.op |= RT_CLEAR_COLOR;
1082                     if (!(reqTarget.op & RT_LOAD_DEPTH) &&  depth) reqTarget.op |= RT_CLEAR_DEPTH;
1083                 }
1084 
1085                 active.target     = target;
1086                 active.targetOp   = reqTarget.op;
1087                 active.targetFace = face;
1088             }
1089         }
1090 
1091         if (mask & RS_VIEWPORT) {
1092             if (viewport != active.viewport) {
1093                 active.viewport = viewport;
1094                 GAPI::setViewport(viewport);
1095             }
1096             renderState &= ~RS_VIEWPORT;
1097         }
1098 
1099         if (mask & RS_SCISSOR) {
1100             if (scissor != active.scissor) {
1101                 active.scissor = scissor;
1102                 GAPI::setScissor(scissor);
1103             }
1104             renderState &= ~RS_SCISSOR;
1105         }
1106 
1107         if (mask & RS_DEPTH_TEST)
1108             GAPI::setDepthTest((renderState & RS_DEPTH_TEST) != 0);
1109 
1110         if (mask & RS_DEPTH_WRITE)
1111             GAPI::setDepthWrite((renderState & RS_DEPTH_WRITE) != 0);
1112 
1113         if (mask & RS_COLOR_WRITE)
1114             GAPI::setColorWrite((renderState & RS_COLOR_WRITE_R) != 0, (renderState & RS_COLOR_WRITE_G) != 0, (renderState & RS_COLOR_WRITE_B) != 0, (renderState & RS_COLOR_WRITE_A) != 0);
1115 
1116         if (mask & RS_CULL)
1117             GAPI::setCullMode(renderState & RS_CULL);
1118 
1119         if (mask & RS_BLEND)
1120             GAPI::setBlendMode(renderState & RS_BLEND);
1121 
1122         if (mask & RS_DISCARD)
1123             GAPI::setAlphaTest((renderState & RS_DISCARD) != 0);
1124 
1125         if (mask & RS_TARGET) {
1126             GAPI::clear((reqTarget.op & RT_CLEAR_COLOR) != 0, (reqTarget.op & RT_CLEAR_DEPTH) != 0);
1127             renderState &= ~RS_TARGET;
1128         }
1129 
1130         active.renderState = renderState;
1131     }
1132 
setClearColor(const vec4 & color)1133     void setClearColor(const vec4 &color) {
1134         GAPI::setClearColor(color);
1135     }
1136 
setViewport(const short4 & v)1137     void setViewport(const short4 &v) {
1138         viewport = v;
1139         renderState |= RS_VIEWPORT;
1140     }
1141 
setViewport(int x,int y,int width,int height)1142     void setViewport(int x, int y, int width, int height) {
1143         setViewport(short4(x, y, width, height));
1144     }
1145 
setScissor(const short4 & s)1146     void setScissor(const short4 &s) {
1147         scissor = s;
1148         renderState |= RS_SCISSOR;
1149     }
1150 
setCullMode(CullMode mode)1151     void setCullMode(CullMode mode) {
1152         renderState &= ~RS_CULL;
1153         switch (mode) {
1154             case cmBack  : renderState |= RS_CULL_BACK;  break;
1155             case cmFront : renderState |= RS_CULL_FRONT; break;
1156             default      : ;
1157         }
1158     }
1159 
setBlendMode(BlendMode mode)1160     void setBlendMode(BlendMode mode) {
1161         renderState &= ~RS_BLEND;
1162         switch (mode) {
1163             case bmAlpha    : renderState |= RS_BLEND_ALPHA;   break;
1164             case bmAdd      : renderState |= RS_BLEND_ADD;     break;
1165             case bmMult     : renderState |= RS_BLEND_MULT;    break;
1166             case bmPremult  : renderState |= RS_BLEND_PREMULT; break;
1167             default         : ;
1168         }
1169     }
1170 
setAlphaTest(bool enable)1171     void setAlphaTest(bool enable) {
1172         renderState &= ~RS_DISCARD;
1173         if (enable)
1174             renderState |= RS_DISCARD;
1175     }
1176 
setColorWrite(bool r,bool g,bool b,bool a)1177     void setColorWrite(bool r, bool g, bool b, bool a) {
1178         renderState &= ~RS_COLOR_WRITE;
1179         if (r) renderState |= RS_COLOR_WRITE_R;
1180         if (g) renderState |= RS_COLOR_WRITE_G;
1181         if (b) renderState |= RS_COLOR_WRITE_B;
1182         if (a) renderState |= RS_COLOR_WRITE_A;
1183     }
1184 
setDepthWrite(bool enable)1185     void setDepthWrite(bool enable) {
1186         if (enable)
1187             renderState |= RS_DEPTH_WRITE;
1188         else
1189             renderState &= ~RS_DEPTH_WRITE;
1190     }
1191 
setDepthTest(bool enable)1192     void setDepthTest(bool enable) {
1193         if (enable)
1194             renderState |= RS_DEPTH_TEST;
1195         else
1196             renderState &= ~RS_DEPTH_TEST;
1197     }
1198 
1199     void setTarget(GAPI::Texture *color, GAPI::Texture *depth, int op, int face = 0) {
1200         if (!color)
1201             color = defaultTarget;
1202 
1203         bool isColor = !color || (color->fmt != FMT_DEPTH && color->fmt != FMT_SHADOW);
1204         setColorWrite(isColor, isColor, isColor, isColor);
1205 
1206         if (color == defaultTarget) // backbuffer
1207             setViewport(viewportDef);
1208         else
1209             setViewport(0, 0, color->origWidth, color->origHeight);
1210 
1211         setScissor(viewport);
1212 
1213         reqTarget.texture = color;
1214         reqTarget.op      = op;
1215         reqTarget.face    = face;
1216         renderState |= RS_TARGET;
1217     }
1218 
setBasis(Basis * basis,int count)1219     void setBasis(Basis *basis, int count) {
1220         Core::active.basis      = basis;
1221         Core::active.basisCount = count;
1222 
1223     #ifndef MERGE_MODELS
1224         count = min(1, count);
1225     #endif
1226 
1227         Core::active.shader->setParam(uBasis, *(vec4*)basis, count * 2);
1228     }
1229 
setMaterial(float diffuse,float ambient,float specular,float alpha)1230     void setMaterial(float diffuse, float ambient, float specular, float alpha) {
1231         Core::active.material = vec4(diffuse, ambient, specular, alpha);
1232 
1233         Core::active.shader->setParam(uMaterial, Core::active.material);
1234     }
1235 
setFog(const vec4 & params)1236     void setFog(const vec4 &params) {
1237     #if defined(_GAPI_D3D8) || defined(_GAPI_C3D) || defined(_GAPI_SW) || defined(FFP)
1238         GAPI::setFog(params);
1239     #else
1240         ASSERT(Core::active.shader);
1241         Core::active.shader->setParam(uFogParams, params);
1242     #endif
1243     }
1244 
updateLights()1245     void updateLights() {
1246         GAPI::updateLights(lightPos, lightColor, MAX_LIGHTS);
1247     }
1248 
resetLights()1249     void resetLights() {
1250         for (int i = 0; i < MAX_LIGHTS; i++) {
1251             lightPos[i]   = vec4(0, 0, 0, 0);
1252             lightColor[i] = vec4(0, 0, 0, 1);
1253         }
1254         updateLights();
1255     }
1256 
pushLights()1257     void pushLights() {
1258         ASSERT(lightStackCount < LIGHT_STACK_SIZE);
1259         memcpy(lightStack[lightStackCount].pos,   lightPos,   sizeof(lightPos));
1260         memcpy(lightStack[lightStackCount].color, lightColor, sizeof(lightColor));
1261         lightStackCount++;
1262     }
1263 
popLights()1264     void popLights() {
1265         ASSERT(lightStackCount > 0);
1266         lightStackCount--;
1267         memcpy(lightPos,   lightStack[lightStackCount].pos,   sizeof(lightPos));
1268         memcpy(lightColor, lightStack[lightStackCount].color, sizeof(lightColor));
1269         updateLights();
1270     }
1271 
copyTarget(Texture * dst,int xOffset,int yOffset,int x,int y,int width,int height)1272     void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
1273         validateRenderState();
1274         GAPI::copyTarget(dst, xOffset, yOffset, x, y, width, height);
1275     }
1276 
copyPixel(int x,int y)1277     vec4 copyPixel(int x, int y) { // GPU sync!
1278         validateRenderState();
1279         return GAPI::copyPixel(x, y);
1280     }
1281 
reset()1282     void reset() {
1283         GAPI::resetState();
1284 
1285         memset(&active, 0, sizeof(active));
1286         renderState = 0;
1287 
1288         setViewport(Core::x, Core::y, Core::width, Core::height);
1289         viewportDef = viewport;
1290         scissor     = viewport;
1291 
1292         setCullMode(cmFront);
1293         setBlendMode(bmAlpha);
1294         setDepthTest(true);
1295         setDepthWrite(true);
1296         setColorWrite(true, true, true, true);
1297         validateRenderState();
1298     }
1299 
beginFrame()1300     bool beginFrame() {
1301         Core::stats.start();
1302         return GAPI::beginFrame();
1303     }
1304 
endFrame()1305     void endFrame() {
1306         if (active.target != defaultTarget) {
1307             GAPI::setTarget(NULL, NULL, 0);
1308             validateRenderState();
1309         }
1310         GAPI::endFrame();
1311         Core::stats.stop();
1312     }
1313 
setViewProj(const mat4 & mView,const mat4 & mProj)1314     void setViewProj(const mat4 &mView, const mat4 &mProj) {
1315         Core::mProj     = mProj;
1316         Core::mView     = mView;
1317         Core::mViewProj = mProj * mView;
1318 
1319         GAPI::setViewProj(mView, mProj);
1320     }
1321 
DIP(GAPI::Mesh * mesh,const MeshRange & range)1322     void DIP(GAPI::Mesh *mesh, const MeshRange &range) {
1323         validateRenderState();
1324 
1325         mesh->bind(range);
1326         GAPI::DIP(mesh, range);
1327 
1328         stats.dips++;
1329         stats.tris += range.iCount / 3;
1330     }
1331 }
1332 
1333 #include "mesh.h"
1334 
1335 #endif
1336