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 ¶ms) {
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