Merge branch '4jcraft:dev' into feat/text-input-support

This commit is contained in:
MatthewBeshay 2026-03-30 13:12:06 +11:00 committed by GitHub
commit 31f6e7012c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 3620 additions and 1916 deletions

View file

@ -1,132 +1,38 @@
name: Build (Linux, x86_64)
name: Build (Linux, x86-64)
on:
push:
paths:
paths: &workflow_paths
- '**.cpp'
- '**.h'
- '**.c'
- '**/meson.build'
- 'meson.build'
- '**/CMakeLists.txt'
- 'CMakeLists.txt'
- '**.cc'
- '**.cxx'
- '**.hh'
- '**.hpp'
- '**.hxx'
- '**.inl'
- "**meson.build"
- "flake.nix"
- '.github/workflows/build-linux.yml'
pull_request:
paths:
- '**.cpp'
- '**.h'
- '**.c'
- '**/meson.build'
- 'meson.build'
- '**/CMakeLists.txt'
- 'CMakeLists.txt'
- '.github/workflows/build-linux.yml'
paths: *workflow_paths
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential ccache python3 python3-pip ninja-build libsdl2-dev libgl-dev libglu1-mesa-dev libpthread-stubs0-dev
python -m pip install meson
# Set a reasonable ccache size
ccache -M 5G || true
- name: Restore ccache
uses: actions/cache@v4
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
path: ~/.ccache
key: ${{ runner.os }}-ccache-${{ hashFiles('**/meson.build') }}
nix_path: nixpkgs=channel:nixos-unstable
- name: Restore meson cache
uses: actions/cache@v4
with:
path: ~/.cache/meson
key: ${{ runner.os }}-meson-${{ hashFiles('**/meson.build') }}
- name: Build
run: nix build --print-build-logs
- name: Configure Meson
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
mkdir -p "$CCACHE_DIR"
export CCACHE_DIR="$CCACHE_DIR"
meson setup build_release --wipe --buildtype=release --native-file=./scripts/llvm_native.txt
- name: Build with Meson
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
export CCACHE_DIR="${{ runner.temp }}/ccache"
# Use all available cores for faster parallel builds
meson compile -C build_release -j $(nproc) -v Minecraft.Client
- name: Install patchelf
run: sudo apt-get install -y patchelf
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: minecraft-client-linux-release_exe-${{ github.sha }}
path: build_release/Minecraft.Client/Minecraft.Client
retention-days: 7
build-linux-debug:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential ccache python3 python3-pip ninja-build libsdl2-dev libgl-dev libglu1-mesa-dev libpthread-stubs0-dev
python -m pip install meson
# Set a reasonable ccache size
ccache -M 5G || true
- name: Restore ccache
uses: actions/cache@v4
with:
path: ~/.ccache
key: ${{ runner.os }}-ccache-debug-${{ hashFiles('**/meson.build') }}
- name: Restore meson cache
uses: actions/cache@v4
with:
path: ~/.cache/meson
key: ${{ runner.os }}-meson-debug-${{ hashFiles('**/meson.build') }}
- name: Configure Meson (debug)
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
mkdir -p "$CCACHE_DIR"
export CCACHE_DIR="$CCACHE_DIR"
meson setup build_debug --wipe --buildtype=debug --native-file=./scripts/llvm_native.txt
- name: Build Debug with Meson
env:
CC: "ccache clang"
CXX: "ccache clang++"
CCACHE_DIR: ${{ runner.temp }}/ccache
run: |
export CCACHE_DIR="${{ runner.temp }}/ccache"
# Use all available cores for faster parallel builds
meson compile -C build_debug -j $(nproc) -v Minecraft.Client
- name: Upload debug executable
uses: actions/upload-artifact@v4
with:
name: minecraft-client-linux-debug_exe-${{ github.sha }}
path: build_debug/Minecraft.Client/Minecraft.Client
retention-days: 7
- name: Flake integrity
run: nix flake check

View file

@ -1,22 +1,8 @@
name: Clang Format
name: Format Check
on:
push:
paths:
- '**.cpp'
- '**.h'
- '**.c'
- '**.cc'
- '**.cxx'
- '**.hh'
- '**.hpp'
- '**.hxx'
- '**.inl'
- '.clang-format'
- '.github/workflows/clang-format.yml'
- '.github/scripts/check-clang-format.sh'
pull_request:
paths:
paths: &workflow_paths
- '**.cpp'
- '**.h'
- '**.c'
@ -30,26 +16,29 @@ on:
- '.github/workflows/clang-format.yml'
- '.github/scripts/check-clang-format.sh'
pull_request:
paths: *workflow_paths
jobs:
clang-format:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
concurrency:
group: clang-format-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-depth: 2
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format-19
uses: daaku/gh-action-apt-install@v4
with:
packages: clang-format
- name: Check changed files
env:
CLANG_FORMAT_BIN: clang-format-19
CLANG_FORMAT_BIN: clang-format
EVENT_NAME: ${{ github.event_name }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}

View file

@ -10,7 +10,12 @@ UIControl::UIControl() {
m_controlName = "";
m_isVisible = true;
m_bHidden = false;
m_isValid = false;
m_eControlType = eNoControl;
m_x = 0;
m_y = 0;
m_width = 0;
m_height = 0;
}
bool UIControl::setupControl(UIScene* scene, IggyValuePath* parent,
@ -20,6 +25,7 @@ bool UIControl::setupControl(UIScene* scene, IggyValuePath* parent,
rrbool res =
IggyValuePathMakeNameRef(&m_iggyPath, parent, controlName.c_str());
m_isValid = res ? true : false;
m_nameXPos = registerFastName(L"x");
m_nameYPos = registerFastName(L"y");
@ -28,16 +34,32 @@ bool UIControl::setupControl(UIScene* scene, IggyValuePath* parent,
m_funcSetAlpha = registerFastName(L"SetControlAlpha");
m_nameVisible = registerFastName(L"visible");
F64 fx, fy, fwidth, fheight;
IggyValueGetF64RS(getIggyValuePath(), m_nameXPos, NULL, &fx);
IggyValueGetF64RS(getIggyValuePath(), m_nameYPos, NULL, &fy);
IggyValueGetF64RS(getIggyValuePath(), m_nameWidth, NULL, &fwidth);
IggyValueGetF64RS(getIggyValuePath(), m_nameHeight, NULL, &fheight);
if (m_isValid) {
IggyDatatype controlType = IGGY_DATATYPE__invalid_request;
IggyResult typeResult =
IggyValueGetTypeRS(getIggyValuePath(), 0, NULL, &controlType);
m_isValid = typeResult == IGGY_RESULT_SUCCESS &&
controlType != IGGY_DATATYPE__invalid_request &&
controlType != IGGY_DATATYPE_undefined;
}
m_x = (S32)fx;
m_y = (S32)fy;
m_width = (S32)Math::round(fwidth);
m_height = (S32)Math::round(fheight);
if (m_isValid) {
F64 fx, fy, fwidth, fheight;
IggyValueGetF64RS(getIggyValuePath(), m_nameXPos, NULL, &fx);
IggyValueGetF64RS(getIggyValuePath(), m_nameYPos, NULL, &fy);
IggyValueGetF64RS(getIggyValuePath(), m_nameWidth, NULL, &fwidth);
IggyValueGetF64RS(getIggyValuePath(), m_nameHeight, NULL, &fheight);
m_x = (S32)fx;
m_y = (S32)fy;
m_width = (S32)Math::round(fwidth);
m_height = (S32)Math::round(fheight);
} else {
m_x = 0;
m_y = 0;
m_width = 0;
m_height = 0;
}
return res;
}
@ -57,6 +79,8 @@ void UIControl::UpdateControl() {
#endif // __PSVITA__
void UIControl::ReInit() {
if (!m_isValid) return;
if (m_lastOpacity != 1.0f) {
IggyDataValue result;
IggyDataValue value[2];
@ -91,6 +115,7 @@ S32 UIControl::getHeight() { return m_height; }
void UIControl::setOpacity(float percent) {
if (percent != m_lastOpacity) {
m_lastOpacity = percent;
if (!m_isValid) return;
IggyDataValue result;
IggyDataValue value[2];
@ -112,6 +137,11 @@ void UIControl::setOpacity(float percent) {
void UIControl::setVisible(bool visible) {
if (visible != m_isVisible) {
if (!m_isValid) {
m_isVisible = visible;
return;
}
rrbool succ = IggyValueSetBooleanRS(getIggyValuePath(), m_nameVisible,
NULL, visible);
if (succ)
@ -122,6 +152,8 @@ void UIControl::setVisible(bool visible) {
}
bool UIControl::getVisible() {
if (!m_isValid) return m_isVisible;
rrbool bVisible = false;
IggyResult result = IggyValueGetBooleanRS(getIggyValuePath(), m_nameVisible,

View file

@ -34,6 +34,7 @@ protected:
eUIControlType m_eControlType;
int m_id;
bool m_bHidden; // set by the Remove call
bool m_isValid;
public:
void setControlType(eUIControlType eType) { m_eControlType = eType; }
@ -83,6 +84,7 @@ public:
void setVisible(bool visible);
bool getVisible();
bool isVisible() { return m_isVisible; }
bool isValid() { return m_isValid; }
virtual bool hasFocus() { return false; }

View file

@ -77,6 +77,16 @@ static void RADLINK WarningCallback(void* user_callback_data, Iggy* player,
// IGGY_RESULT_Error_UndefinedEntity = 504,
// IGGY_RESULT_Error_OutOfMemory = 1001,};
if (message != NULL) {
// 4jcraft: Some Linux movie variants do not ship these optional
// hooks/controls. We guard the call sites, so drop the residual Iggy
// warning noise.
if (strstr(message, "LabelGamertag") != NULL ||
strstr(message, "Method SetSafeZone was not a function") != NULL) {
return;
}
}
switch (code) {
case IGGY_RESULT_Warning_CannotSustainFrameRate:
// Ignore warning
@ -3233,4 +3243,4 @@ void UIController::SendTouchInput(unsigned int iPad, unsigned int key,
}
}
#endif
#endif

View file

@ -19,6 +19,7 @@ UIScene::UIScene(int iPad, UILayer* parentLayer) {
m_bVisible = true;
m_bCanHandleInput = false;
m_bIsReloading = false;
m_hasSetSafeZoneMethod = false;
m_iFocusControl = -1;
m_iFocusChild = 0;
@ -53,6 +54,7 @@ void UIScene::destroyMovie() {
/* Destroy the Iggy player. */
IggyPlayerDestroy(swf);
swf = NULL;
m_hasSetSafeZoneMethod = false;
// Clear out the controls collection (doesn't delete the controls, and they
// get re-setup later)
@ -76,6 +78,7 @@ void UIScene::reloadMovie(bool force) {
// Clear out the controls collection (doesn't delete the controls, and
// they get re-setup later)
m_controls.clear();
m_hasSetSafeZoneMethod = false;
// Clear out all the fast names for the current movie
m_fastNames.clear();
@ -194,6 +197,8 @@ void UIScene::updateSafeZone() {
void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft,
S32 safeRight) {
if (!m_hasSetSafeZoneMethod) return;
IggyDataValue result;
IggyDataValue value[4];
@ -251,6 +256,13 @@ bool UIScene::mapElementsAndNames() {
m_funcSetAlpha = registerFastName(L"SetAlpha");
m_funcSetFocus = registerFastName(L"SetFocus");
m_funcHorizontalResizeCheck = registerFastName(L"DoHorizontalResizeCheck");
IggyDatatype safeZoneType = IGGY_DATATYPE__invalid_request;
IggyResult safeZoneResult = IggyValueGetTypeRS(
m_rootPath, m_funcSetSafeZone, NULL, &safeZoneType);
m_hasSetSafeZoneMethod =
safeZoneResult == IGGY_RESULT_SUCCESS &&
safeZoneType == IGGY_DATATYPE_function;
return true;
}
@ -712,7 +724,7 @@ void UIScene::_customDrawSlotControl(CustomDrawData* region, int iPad,
}
glEnable(GL_RESCALE_NORMAL);
glPushMatrix();
Lighting::turnOnGui();
Lighting::turnOn();
glRotatef(120, 1, 0, 0);
glPopMatrix();

View file

@ -72,6 +72,7 @@ private:
bool m_bUpdateOpacity;
bool m_bVisible;
bool m_bCanHandleInput;
bool m_hasSetSafeZoneMethod;
UIScene* m_backScene;
size_t m_callbackUniqueId;

View file

@ -5,8 +5,6 @@
#include "../../Minecraft.Client/Minecraft.h"
#include "UIScene_EnchantingMenu.h"
#include <print>
UIScene_EnchantingMenu::UIScene_EnchantingMenu(int iPad, void* _initData,
UILayer* parentLayer)
: UIScene_AbstractContainerMenu(iPad, parentLayer) {

View file

@ -0,0 +1,835 @@
#define GDRAW_ASSERTS
#include "../../../Windows64/Iggy/include/iggy.h"
#include "../../../Windows64/Iggy/include/gdraw.h"
#include "gdraw.h"
#include <GL/gl.h>
#include <GL/glext.h>
#include <SDL2/SDL.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <dlfcn.h>
#define true 1
#define false 0
#ifndef _ENABLEIGGY
void* IggyGDrawMallocAnnotated(SINTa size, const char* file, int line) {
(void)file;
(void)line;
return malloc((size_t)size);
}
void IggyGDrawFree(void* ptr) { free(ptr); }
void IggyGDrawSendWarning(Iggy* f, char const* message, ...) {
(void)f;
va_list args;
va_start(args, message);
fprintf(stderr, "[Iggy GDraw Warning] ");
vfprintf(stderr, message, args);
fprintf(stderr, "\n");
va_end(args);
}
void IggyDiscardVertexBufferCallback(void* owner, void* buf) {
(void)owner;
(void)buf;
}
#endif
static void* get_gl_proc(const char* name) {
void* p = SDL_GL_GetProcAddress(name);
if (!p) p = dlsym(RTLD_DEFAULT, name);
if (!p) {
char buf[256];
strncpy(buf, name, sizeof(buf) - 1);
buf[255] = '\0';
char* ext = strstr(buf, "ARB");
if (!ext) ext = strstr(buf, "EXT");
if (ext && ext == buf + strlen(buf) - 3) {
*ext = '\0';
p = SDL_GL_GetProcAddress(buf);
if (!p) p = dlsym(RTLD_DEFAULT, buf);
}
}
return p;
}
#define GDRAW_GL_EXTENSION_LIST \
/* identifier import procname */ \
/* GL_ARB_vertex_buffer_object */ \
GLE(GenBuffers, "GenBuffersARB", GENBUFFERSARB) \
GLE(DeleteBuffers, "DeleteBuffersARB", DELETEBUFFERSARB) \
GLE(BindBuffer, "BindBufferARB", BINDBUFFERARB) \
GLE(BufferData, "BufferDataARB", BUFFERDATAARB) \
GLE(MapBuffer, "MapBufferARB", MAPBUFFERARB) \
GLE(UnmapBuffer, "UnmapBufferARB", UNMAPBUFFERARB) \
GLE(VertexAttribPointer, "VertexAttribPointerARB", VERTEXATTRIBPOINTERARB) \
GLE(EnableVertexAttribArray, "EnableVertexAttribArrayARB", \
ENABLEVERTEXATTRIBARRAYARB) \
GLE(DisableVertexAttribArray, "DisableVertexAttribArrayARB", \
DISABLEVERTEXATTRIBARRAYARB) \
/* GL_ARB_shader_objects */ \
GLE(CreateShader, "CreateShaderObjectARB", CREATESHADEROBJECTARB) \
GLE(DeleteShader, "DeleteObjectARB", DELETEOBJECTARB) \
GLE(ShaderSource, "ShaderSourceARB", SHADERSOURCEARB) \
GLE(CompileShader, "CompileShaderARB", COMPILESHADERARB) \
GLE(GetShaderiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
GLE(GetShaderInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
GLE(CreateProgram, "CreateProgramObjectARB", CREATEPROGRAMOBJECTARB) \
GLE(DeleteProgram, "DeleteObjectARB", DELETEOBJECTARB) \
GLE(AttachShader, "AttachObjectARB", ATTACHOBJECTARB) \
GLE(LinkProgram, "LinkProgramARB", LINKPROGRAMARB) \
GLE(GetUniformLocation, "GetUniformLocationARB", GETUNIFORMLOCATIONARB) \
GLE(UseProgram, "UseProgramObjectARB", USEPROGRAMOBJECTARB) \
GLE(GetProgramiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
GLE(GetProgramInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
GLE(Uniform1i, "Uniform1iARB", UNIFORM1IARB) \
GLE(Uniform4f, "Uniform4fARB", UNIFORM4FARB) \
GLE(Uniform4fv, "Uniform4fvARB", UNIFORM4FVARB) \
/* GL_ARB_vertex_shader */ \
GLE(BindAttribLocation, "BindAttribLocationARB", BINDATTRIBLOCATIONARB) \
/* Missing from WGL but needed by shared code */ \
GLE(Uniform1f, "Uniform1fARB", UNIFORM1FARB) \
/* GL_EXT_framebuffer_object */ \
GLE(GenRenderbuffers, "GenRenderbuffersEXT", GENRENDERBUFFERSEXT) \
GLE(DeleteRenderbuffers, "DeleteRenderbuffersEXT", DELETERENDERBUFFERSEXT) \
GLE(BindRenderbuffer, "BindRenderbufferEXT", BINDRENDERBUFFEREXT) \
GLE(RenderbufferStorage, "RenderbufferStorageEXT", RENDERBUFFERSTORAGEEXT) \
GLE(GenFramebuffers, "GenFramebuffersEXT", GENFRAMEBUFFERSEXT) \
GLE(DeleteFramebuffers, "DeleteFramebuffersEXT", DELETEFRAMEBUFFERSEXT) \
GLE(BindFramebuffer, "BindFramebufferEXT", BINDFRAMEBUFFEREXT) \
GLE(CheckFramebufferStatus, "CheckFramebufferStatusEXT", \
CHECKFRAMEBUFFERSTATUSEXT) \
GLE(FramebufferRenderbuffer, "FramebufferRenderbufferEXT", \
FRAMEBUFFERRENDERBUFFEREXT) \
GLE(FramebufferTexture2D, "FramebufferTexture2DEXT", \
FRAMEBUFFERTEXTURE2DEXT) \
GLE(GenerateMipmap, "GenerateMipmapEXT", GENERATEMIPMAPEXT) \
/* GL_EXT_framebuffer_blit */ \
GLE(BlitFramebuffer, "BlitFramebufferEXT", BLITFRAMEBUFFEREXT) \
/* GL_EXT_framebuffer_multisample */ \
GLE(RenderbufferStorageMultisample, "RenderbufferStorageMultisampleEXT", \
RENDERBUFFERSTORAGEMULTISAMPLEEXT) \
/* <end> */
// Shared .inl
#define gdraw_GLx_(id) gdraw_GL_##id
#define GDRAW_GLx_(id) GDRAW_GL_##id
#define GDRAW_SHADERS "gdraw_gl_shaders.inl"
// GLhandleARB is void* but shader functions use GLuint values.
// homework stolen from gdraw_gl_shared.inl.
#define GDrawGLProgram GLuint
typedef GLuint GLhandle;
typedef gdraw_gl_resourcetype gdraw_resourcetype;
#define GLE(id, import, procname) static PFNGL##procname##PROC gl##id;
GDRAW_GL_EXTENSION_LIST
#undef GLE
typedef const GLubyte*(APIENTRYP PFNGLGETSTRINGIPROC_)(GLenum name,
GLuint index);
static PFNGLGETSTRINGIPROC_ gdraw_glGetStringi = NULL;
typedef void(APIENTRYP PFNGLGENVERTEXARRAYSPROC_)(GLsizei n, GLuint* arrays);
typedef void(APIENTRYP PFNGLBINDVERTEXARRAYPROC_)(GLuint array);
static PFNGLGENVERTEXARRAYSPROC_ gdraw_glGenVertexArrays = NULL;
static PFNGLBINDVERTEXARRAYPROC_ gdraw_glBindVertexArray = NULL;
static GLuint gdraw_vao = 0;
typedef void(APIENTRYP gdraw_vtxattrib_fn)(GLuint, GLint, GLenum, GLboolean,
GLsizei, const void*);
static gdraw_vtxattrib_fn gdraw_real_vtxattrib = NULL;
static GLuint gdraw_screenvbo = 0;
static const void* gdraw_screenvbo_base = NULL;
static size_t gdraw_expected_vbo_size = 0;
typedef void(APIENTRYP gdraw_drawelements_fn)(GLenum mode, GLsizei count,
GLenum type, const void* indices);
static gdraw_drawelements_fn gdraw_real_drawelements = NULL;
static GLuint gdraw_screenibo = 0;
typedef GLuint(APIENTRYP gdraw_createshader_fn)(GLenum);
typedef void(APIENTRYP gdraw_shadersource_fn)(GLuint, GLsizei, const GLchar**,
const GLint*);
typedef void(APIENTRYP gdraw_compileshader_fn)(GLuint);
typedef void(APIENTRYP gdraw_linkprogram_fn)(GLuint);
static gdraw_createshader_fn gdraw_real_createshader = NULL;
static gdraw_shadersource_fn gdraw_real_shadersource = NULL;
static gdraw_compileshader_fn gdraw_real_compileshader = NULL;
static gdraw_linkprogram_fn gdraw_real_linkprogram = NULL;
// some core reject p0
typedef void(APIENTRYP gdraw_useprogram_fn)(GLuint);
static gdraw_useprogram_fn gdraw_real_useprogram = NULL;
static GLuint gdraw_null_program = 0;
typedef void(APIENTRYP gdraw_teximage2d_fn)(GLenum, GLint, GLint, GLsizei,
GLsizei, GLint, GLenum, GLenum,
const void*);
typedef void(APIENTRYP gdraw_texsubimage2d_fn)(GLenum, GLint, GLint, GLint,
GLsizei, GLsizei, GLenum, GLenum,
const void*);
static gdraw_teximage2d_fn gdraw_real_teximage2d = NULL;
static gdraw_texsubimage2d_fn gdraw_real_texsubimage2d = NULL;
#define TRY(ptr, arb, core) \
do { \
void* _p = get_gl_proc(core); \
if (!_p) _p = get_gl_proc(arb); \
*(void**)&(ptr) = _p; \
} while (0)
static void load_extensions(void) {
// gl_shared requires ts shit ugh
#define GLE(id, import, procname) \
gl##id = (PFNGL##procname##PROC)get_gl_proc("gl" import);
GDRAW_GL_EXTENSION_LIST
#undef GLE
TRY(glCreateShader, "glCreateShaderObjectARB", "glCreateShader");
TRY(glDeleteShader, "glDeleteObjectARB", "glDeleteShader");
TRY(glShaderSource, "glShaderSourceARB", "glShaderSource");
TRY(glCompileShader, "glCompileShaderARB", "glCompileShader");
TRY(glGetShaderiv, "glGetObjectParameterivARB", "glGetShaderiv");
TRY(glGetShaderInfoLog, "glGetInfoLogARB", "glGetShaderInfoLog");
TRY(glCreateProgram, "glCreateProgramObjectARB", "glCreateProgram");
TRY(glDeleteProgram, "glDeleteObjectARB", "glDeleteProgram");
TRY(glAttachShader, "glAttachObjectARB", "glAttachShader");
TRY(glLinkProgram, "glLinkProgramARB", "glLinkProgram");
TRY(glGetUniformLocation, "glGetUniformLocationARB",
"glGetUniformLocation");
TRY(glUseProgram, "glUseProgramObjectARB", "glUseProgram");
TRY(glGetProgramiv, "glGetObjectParameterivARB", "glGetProgramiv");
TRY(glGetProgramInfoLog, "glGetInfoLogARB", "glGetProgramInfoLog");
TRY(glUniform1i, "glUniform1iARB", "glUniform1i");
TRY(glUniform4f, "glUniform4fARB", "glUniform4f");
TRY(glUniform4fv, "glUniform4fvARB", "glUniform4fv");
TRY(glUniform1f, "glUniform1fARB", "glUniform1f");
TRY(glBindAttribLocation, "glBindAttribLocationARB",
"glBindAttribLocation");
TRY(glGenBuffers, "glGenBuffersARB", "glGenBuffers");
TRY(glDeleteBuffers, "glDeleteBuffersARB", "glDeleteBuffers");
TRY(glBindBuffer, "glBindBufferARB", "glBindBuffer");
TRY(glBufferData, "glBufferDataARB", "glBufferData");
TRY(glMapBuffer, "glMapBufferARB", "glMapBuffer");
TRY(glUnmapBuffer, "glUnmapBufferARB", "glUnmapBuffer");
TRY(glVertexAttribPointer, "glVertexAttribPointerARB",
"glVertexAttribPointer");
TRY(glEnableVertexAttribArray, "glEnableVertexAttribArrayARB",
"glEnableVertexAttribArray");
TRY(glDisableVertexAttribArray, "glDisableVertexAttribArrayARB",
"glDisableVertexAttribArray");
TRY(glGenRenderbuffers, "glGenRenderbuffersEXT", "glGenRenderbuffers");
TRY(glDeleteRenderbuffers, "glDeleteRenderbuffersEXT",
"glDeleteRenderbuffers");
TRY(glBindRenderbuffer, "glBindRenderbufferEXT", "glBindRenderbuffer");
TRY(glRenderbufferStorage, "glRenderbufferStorageEXT",
"glRenderbufferStorage");
TRY(glGenFramebuffers, "glGenFramebuffersEXT", "glGenFramebuffers");
TRY(glDeleteFramebuffers, "glDeleteFramebuffersEXT",
"glDeleteFramebuffers");
TRY(glBindFramebuffer, "glBindFramebufferEXT", "glBindFramebuffer");
TRY(glCheckFramebufferStatus, "glCheckFramebufferStatusEXT",
"glCheckFramebufferStatus");
TRY(glFramebufferRenderbuffer, "glFramebufferRenderbufferEXT",
"glFramebufferRenderbuffer");
TRY(glFramebufferTexture2D, "glFramebufferTexture2DEXT",
"glFramebufferTexture2D");
TRY(glGenerateMipmap, "glGenerateMipmapEXT", "glGenerateMipmap");
TRY(glBlitFramebuffer, "glBlitFramebufferEXT", "glBlitFramebuffer");
TRY(glRenderbufferStorageMultisample, "glRenderbufferStorageMultisampleEXT",
"glRenderbufferStorageMultisample");
// Save raw pointers before we #define over the names below
gdraw_real_vtxattrib =
(gdraw_vtxattrib_fn)get_gl_proc("glVertexAttribPointer");
gdraw_real_createshader =
(gdraw_createshader_fn)get_gl_proc("glCreateShader");
gdraw_real_shadersource =
(gdraw_shadersource_fn)get_gl_proc("glShaderSource");
gdraw_real_compileshader =
(gdraw_compileshader_fn)get_gl_proc("glCompileShader");
gdraw_real_linkprogram = (gdraw_linkprogram_fn)get_gl_proc("glLinkProgram");
gdraw_real_teximage2d = (gdraw_teximage2d_fn)get_gl_proc("glTexImage2D");
gdraw_real_texsubimage2d =
(gdraw_texsubimage2d_fn)get_gl_proc("glTexSubImage2D");
gdraw_real_useprogram = (gdraw_useprogram_fn)get_gl_proc("glUseProgram");
gdraw_real_drawelements =
(gdraw_drawelements_fn)get_gl_proc("glDrawElements");
gdraw_glGetStringi = (PFNGLGETSTRINGIPROC_)get_gl_proc("glGetStringi");
gdraw_glGenVertexArrays =
(PFNGLGENVERTEXARRAYSPROC_)get_gl_proc("glGenVertexArrays");
gdraw_glBindVertexArray =
(PFNGLBINDVERTEXARRAYPROC_)get_gl_proc("glBindVertexArray");
if (gdraw_glGenVertexArrays && gdraw_glBindVertexArray && gdraw_vao == 0) {
gdraw_glGenVertexArrays(1, &gdraw_vao);
gdraw_glBindVertexArray(gdraw_vao);
}
}
#undef TRY
// rebind vbo
static void clear_renderstate_platform_specific(void) {
if (gdraw_glBindVertexArray && gdraw_vao)
gdraw_glBindVertexArray(gdraw_vao);
}
static void error_msg_platform_specific(const char* msg) {
fprintf(stderr, "[GDraw] %s\n", msg);
}
#define GDRAW_PLATFORM_REPORT_GL_SITE(site) \
do { \
if ((site) != NULL) \
fprintf(stderr, "[GDraw] GL error site: %s\n", (site)); \
} while (0)
#define GDRAW_MULTISAMPLING
// i wish i could improve this function
#ifdef RR_BREAK
#undef RR_BREAK
#endif
#define RR_BREAK() \
do { \
fprintf(stderr, "[GDraw] GL error at %s:%d\n", __FILE__, __LINE__); \
} while (0)
// the magic number that tropical told me
#define GDRAW_MAX_SHADERS 64
static struct {
GLuint handle;
GLenum type;
} gdraw_shader_types[GDRAW_MAX_SHADERS];
static int gdraw_shader_type_count = 0;
static GLenum gdraw_get_shader_type(GLuint shader) {
for (int i = 0; i < gdraw_shader_type_count; i++)
if (gdraw_shader_types[i].handle == shader)
return gdraw_shader_types[i].type;
return GL_FRAGMENT_SHADER;
}
static GLuint gdraw_CreateShaderTracked(GLenum type) {
GLuint h = gdraw_real_createshader(type);
if (h && gdraw_shader_type_count < GDRAW_MAX_SHADERS) {
gdraw_shader_types[gdraw_shader_type_count].handle = h;
gdraw_shader_types[gdraw_shader_type_count].type = type;
gdraw_shader_type_count++;
}
return h;
}
static void gdraw_CompileShaderAndLog(GLuint shader) {
GLint status = 0;
gdraw_real_compileshader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
char log[2048];
GLint len = 0;
glGetShaderInfoLog(shader, (GLsizei)sizeof(log) - 1, &len, log);
log[len] = '\0';
fprintf(stderr, "[GDraw GLSL] compile FAILED shader=%u:\n%s\n", shader,
log);
}
}
static void gdraw_LinkProgramAndLog(GLuint program) {
GLint status = 0;
gdraw_real_linkprogram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (!status) {
char log[2048];
GLint len = 0;
glGetProgramInfoLog(program, (GLsizei)sizeof(log) - 1, &len, log);
log[len] = '\0';
fprintf(stderr, "[GDraw GLSL] link FAILED program=%u:\n%s\n", program,
log);
}
}
#undef glCreateShader
#define glCreateShader gdraw_CreateShaderTracked
// This is the part that turns the old ugly shaders to 330
static char* gdraw_strreplace(char* src, const char* find, const char* rep) {
char* result;
char* pos;
char* base = src;
size_t find_len = strlen(find);
size_t rep_len = strlen(rep);
size_t count = 0;
char* tmp = src;
while ((tmp = strstr(tmp, find))) {
count++;
tmp += find_len;
}
if (!count) return src;
result = (char*)malloc(strlen(src) + count * (rep_len + 1) + 1);
if (!result) return src;
tmp = result;
while ((pos = strstr(src, find))) {
size_t before = (size_t)(pos - src);
memcpy(tmp, src, before);
tmp += before;
memcpy(tmp, rep, rep_len);
tmp += rep_len;
src = pos + find_len;
}
strcpy(tmp, src);
free(base);
return result;
}
static void gdraw_ShaderSourceUpgraded(GLuint shader, GLsizei count,
const GLchar** strings,
const GLint* lengths) {
size_t total = 0;
for (int i = 0; i < count; i++)
total += lengths ? (lengths[i] >= 0 ? (size_t)lengths[i]
: strlen(strings[i]))
: strlen(strings[i]);
char* src = (char*)malloc(total + 1);
if (!src) {
gdraw_real_shadersource(shader, count, strings, lengths);
return;
}
src[0] = '\0';
for (int i = 0; i < count; i++) {
size_t len = lengths ? (lengths[i] >= 0 ? (size_t)lengths[i]
: strlen(strings[i]))
: strlen(strings[i]);
strncat(src, strings[i], len);
}
int is_vert = (gdraw_get_shader_type(shader) == GL_VERTEX_SHADER);
// Strip any existing #version directive as i'll add our own
{
char* vp = strstr(src, "#version");
if (vp) {
char* nl = strchr(vp, '\n');
if (nl)
memmove(vp, nl + 1, strlen(nl + 1) + 1);
else
*vp = '\0';
}
}
// Texture built-ins
src = gdraw_strreplace(src, "texture2DRect", "texture");
src = gdraw_strreplace(src, "texture2D", "texture");
// Attribute -> in
src = gdraw_strreplace(src, "attribute ", "in ");
src = gdraw_strreplace(src, "attribute\t", "in\t");
src = gdraw_strreplace(src, "attribute\n", "in\n");
// Varying -> out (vert) / in (frag)
if (is_vert) {
src = gdraw_strreplace(src, "varying ", "out ");
src = gdraw_strreplace(src, "varying\t", "out\t");
src = gdraw_strreplace(src, "varying\n", "out\n");
} else {
src = gdraw_strreplace(src, "varying ", "in ");
src = gdraw_strreplace(src, "varying\t", "in\t");
src = gdraw_strreplace(src, "varying\n", "in\n");
src = gdraw_strreplace(src, "gl_FragData[0]", "_gdraw_frag_out");
src = gdraw_strreplace(src, "gl_FragColor", "_gdraw_frag_out");
}
const char* header = is_vert
? "#version 330 core\n"
: "#version 330 core\nout vec4 _gdraw_frag_out;\n";
char* patched = (char*)malloc(strlen(header) + strlen(src) + 2);
if (!patched) {
free(src);
gdraw_real_shadersource(shader, count, strings, lengths);
return;
}
strcpy(patched, header);
strcat(patched, src);
free(src);
const GLchar* patched_ptr = (const GLchar*)patched;
gdraw_real_shadersource(shader, 1, &patched_ptr, NULL);
free(patched);
}
#undef glShaderSource
#define glShaderSource gdraw_ShaderSourceUpgraded
// Remap all the deprecated internal formats to their modern equivalents
// (idk why but just the word "swizzle" is cracking me up)
static void gdraw_apply_swizzle(GLenum internal_fmt) {
if (internal_fmt == 0x1906 /* GL_ALPHA */ || internal_fmt == GL_RED) {
GLint sw[4] = {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
} else if (internal_fmt == 0x1909 /* GL_LUMINANCE */) {
GLint sw[4] = {GL_RED, GL_RED, GL_RED, GL_ONE};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
} else if (internal_fmt == 0x190A /* GL_LUMINANCE_ALPHA */) {
GLint sw[4] = {GL_RED, GL_RED, GL_RED, GL_GREEN};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
}
}
static GLenum gdraw_remap_fmt(GLenum fmt) {
switch (fmt) {
case 0x1906:
return GL_RED; // GL_ALPHA
case 0x1909:
return GL_RED; // GL_LUMINANCE
case 0x190A:
return GL_RG; // GL_LUMINANCE_ALPHA
case 0x8033:
return GL_RG; // GL_LUMINANCE4_ALPHA4
case 0x8045:
return GL_R8; // GL_LUMINANCE8
case 0x8048:
return GL_RG8; // GL_LUMINANCE8_ALPHA8
case 0x804F:
return GL_R8; // GL_INTENSITY4
case 0x8050:
return GL_R8; // GL_INTENSITY8
default:
return fmt;
}
}
static void gdraw_TexImage2D(GLenum target, GLint level, GLint ifmt, GLsizei w,
GLsizei h, GLint border, GLenum fmt, GLenum type,
const void* data) {
// ES strictly requires explicitly sized formats & stuff
if (ifmt == GL_RGBA && data == NULL) ifmt = GL_RGBA8;
GLenum new_ifmt = gdraw_remap_fmt((GLenum)ifmt);
GLenum new_fmt = gdraw_remap_fmt(fmt);
gdraw_real_teximage2d(target, level, (GLint)new_ifmt, w, h, border, new_fmt,
type, data);
if (new_ifmt != (GLenum)ifmt) gdraw_apply_swizzle((GLenum)ifmt);
}
static void gdraw_TexSubImage2D(GLenum target, GLint level, GLint xoff,
GLint yoff, GLsizei w, GLsizei h, GLenum fmt,
GLenum type, const void* data) {
GLenum new_fmt = gdraw_remap_fmt(fmt);
gdraw_real_texsubimage2d(target, level, xoff, yoff, w, h, new_fmt, type,
data);
}
#undef glTexImage2D
#define glTexImage2D gdraw_TexImage2D
#undef glTexSubImage2D
#define glTexSubImage2D gdraw_TexSubImage2D
// vbo emu
static void gdraw_ClientVertexAttribPointer(GLuint index, GLint size,
GLenum type, GLboolean normalized,
GLsizei stride,
const void* pointer) {
if (gdraw_glBindVertexArray && gdraw_vao) {
GLint current_vao = 0;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &current_vao);
if ((GLuint)current_vao != gdraw_vao)
gdraw_glBindVertexArray(gdraw_vao);
}
GLint current_vbo = 0;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &current_vbo);
if (current_vbo != 0 && current_vbo != (GLint)gdraw_screenvbo) {
// no touchies
gdraw_real_vtxattrib(index, size, type, normalized, stride, pointer);
return;
}
if (pointer == NULL) {
gdraw_real_vtxattrib(index, size, type, normalized, stride, pointer);
return;
}
ptrdiff_t offset =
gdraw_screenvbo_base
? ((const char*)pointer - (const char*)gdraw_screenvbo_base)
: -1;
if (gdraw_screenvbo_base == NULL || offset < 0 ||
offset >= (ptrdiff_t)gdraw_expected_vbo_size) {
if (!gdraw_screenvbo) glGenBuffers(1, &gdraw_screenvbo);
glBindBuffer(GL_ARRAY_BUFFER, gdraw_screenvbo);
size_t upload_size = gdraw_expected_vbo_size > 0
? (gdraw_expected_vbo_size + 256)
: 65536;
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)upload_size, pointer,
GL_STREAM_DRAW);
gdraw_screenvbo_base = pointer;
gdraw_real_vtxattrib(index, size, type, normalized, stride,
(const void*)0);
} else {
glBindBuffer(GL_ARRAY_BUFFER, gdraw_screenvbo);
gdraw_real_vtxattrib(index, size, type, normalized, stride,
(const void*)offset);
}
}
#undef glVertexAttribPointer
#define glVertexAttribPointer gdraw_ClientVertexAttribPointer
// fake ibo
static void hooked_glDrawElements(GLenum mode, GLsizei count, GLenum type,
const void* indices) {
GLint current_ibo = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &current_ibo);
if (current_ibo == 0 && indices != NULL) {
if (!gdraw_screenibo) glGenBuffers(1, &gdraw_screenibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gdraw_screenibo);
size_t index_size = (type == GL_UNSIGNED_SHORT) ? 2
: (type == GL_UNSIGNED_BYTE) ? 1
: 4;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(count * index_size),
indices, GL_STREAM_DRAW);
gdraw_real_drawelements(mode, count, type, (const void*)0);
} else {
gdraw_real_drawelements(mode, count, type, indices);
}
}
#define glDrawElements hooked_glDrawElements
// dummy shader for glUseProgram(0) safety
static void gdraw_UseProgramSafe(GLuint program) {
if (!program) {
if (!gdraw_null_program && gdraw_real_useprogram) {
const char* vs =
"#version 330 core\nvoid main(){gl_Position=vec4(0);}";
const char* fs =
"#version 330 core\nout vec4 c;\nvoid main(){c=vec4(0);}";
GLuint v = gdraw_real_createshader(GL_VERTEX_SHADER);
GLuint f = gdraw_real_createshader(GL_FRAGMENT_SHADER);
gdraw_real_shadersource(v, 1, &vs, NULL);
gdraw_real_shadersource(f, 1, &fs, NULL);
gdraw_real_compileshader(v);
gdraw_real_compileshader(f);
gdraw_null_program = glCreateProgram();
glAttachShader(gdraw_null_program, v);
glAttachShader(gdraw_null_program, f);
gdraw_real_linkprogram(gdraw_null_program);
glDeleteShader(v);
glDeleteShader(f);
}
gdraw_real_useprogram(gdraw_null_program);
return;
}
gdraw_real_useprogram(program);
}
#undef glUseProgram
#define glUseProgram gdraw_UseProgramSafe
#undef glCompileShader
#define glCompileShader gdraw_CompileShaderAndLog
#undef glLinkProgram
#define glLinkProgram gdraw_LinkProgramAndLog
static void gdraw_FramebufferRenderbufferSafe(GLenum target, GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer) {
static GLuint last_depth_rb = 0;
if (attachment == GL_DEPTH_ATTACHMENT) {
last_depth_rb = renderbuffer;
(glFramebufferRenderbuffer)(target, attachment, renderbuffertarget,
renderbuffer);
} else if (attachment == GL_STENCIL_ATTACHMENT) {
if (renderbuffer == last_depth_rb && renderbuffer != 0) {
// If identical, bind as packed depth-stencil to satisfy strict GLES
// ^ how greedy -n-
(glFramebufferRenderbuffer)(
target, 0x821A /* GL_DEPTH_STENCIL_ATTACHMENT */,
renderbuffertarget, renderbuffer);
} else {
(glFramebufferRenderbuffer)(target, attachment, renderbuffertarget,
renderbuffer);
}
} else {
(glFramebufferRenderbuffer)(target, attachment, renderbuffertarget,
renderbuffer);
}
}
#define glFramebufferRenderbuffer_SAFE gdraw_FramebufferRenderbufferSafe
#define glFramebufferRenderbuffer glFramebufferRenderbuffer_SAFE
#include "../../../Windows64/Iggy/gdraw/gdraw_gl_shared.inl"
#undef glVertexAttribPointer
#define glVertexAttribPointer gdraw_real_vtxattrib
static int hasext_core(const char* name) {
GLint n = 0;
if (!gdraw_glGetStringi) return 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for (GLint i = 0; i < n; i++) {
const char* e =
(const char*)gdraw_glGetStringi(GL_EXTENSIONS, (GLuint)i);
if (e && strcmp(e, name) == 0) return 1;
}
return 0;
}
static gdraw_draw_indexed_triangles* real_DrawIndexedTriangles = NULL;
static void RADLINK hooked_DrawIndexedTriangles(GDrawRenderState* r,
GDrawPrimitive* prim,
GDrawVertexBuffer* buf,
GDrawStats* stats) {
if (buf == NULL && prim != NULL && prim->vertices != NULL) {
size_t stride = 8;
if (prim->vertex_format == GDRAW_vformat_v2aa)
stride = 16;
else if (prim->vertex_format == GDRAW_vformat_v2tc2)
stride = 16;
else if (prim->vertex_format == GDRAW_vformat_ihud1)
stride = 20;
gdraw_expected_vbo_size = prim->num_vertices * stride;
} else {
gdraw_expected_vbo_size = 0;
}
gdraw_screenvbo_base = NULL; // Force VBO re-upload for each primitive
real_DrawIndexedTriangles(r, prim, buf, stats);
}
static gdraw_filter_quad* real_FilterQuad = NULL;
static void RADLINK hooked_FilterQuad(GDrawRenderState* r, S32 x0, S32 y0,
S32 x1, S32 y1, GDrawStats* stats) {
gdraw_expected_vbo_size = 4 * 20; // 4 vertices, max stride
gdraw_screenvbo_base = NULL;
real_FilterQuad(r, x0, y0, x1, y1, stats);
}
static gdraw_rendering_begin* real_RenderingBegin = NULL;
// stupid hack
static void RADLINK hooked_RenderingBegin(void) {
if (real_RenderingBegin) real_RenderingBegin();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
OPENGL_CHECK_SITE("hooked_RenderingBegin:post_state");
}
// Creating the context
GDrawFunctions* gdraw_GL_CreateContext(S32 w, S32 h, S32 msaa_samples) {
static const TextureFormatDesc tex_formats[] = {
{IFT_FORMAT_rgba_8888, 1, 1, 4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
{IFT_FORMAT_rgba_4444_LE, 1, 1, 2, GL_RGBA4, GL_RGBA,
GL_UNSIGNED_SHORT_4_4_4_4},
{IFT_FORMAT_rgba_5551_LE, 1, 1, 2, GL_RGB5_A1, GL_RGBA,
GL_UNSIGNED_SHORT_5_5_5_1},
{IFT_FORMAT_la_88, 1, 1, 2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE},
{IFT_FORMAT_la_44, 1, 1, 1, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE},
{IFT_FORMAT_i_8, 1, 1, 1, GL_INTENSITY8, GL_ALPHA, GL_UNSIGNED_BYTE},
{IFT_FORMAT_i_4, 1, 1, 1, GL_INTENSITY4, GL_ALPHA, GL_UNSIGNED_BYTE},
{IFT_FORMAT_l_8, 1, 1, 1, GL_LUMINANCE8, GL_LUMINANCE,
GL_UNSIGNED_BYTE},
{IFT_FORMAT_l_4, 1, 1, 1, GL_LUMINANCE4, GL_LUMINANCE,
GL_UNSIGNED_BYTE},
{IFT_FORMAT_DXT1, 4, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0,
GL_UNSIGNED_BYTE},
{IFT_FORMAT_DXT3, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0,
GL_UNSIGNED_BYTE},
{IFT_FORMAT_DXT5, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0,
GL_UNSIGNED_BYTE},
{0, 0, 0, 0, 0, 0, 0},
};
GLint major = 0, minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major < 3) {
fprintf(stderr, "[GDraw] GL 3.0 or higher required (got %d.%d)\n",
major, minor);
return NULL;
}
load_extensions();
if (gdraw_glBindVertexArray && gdraw_vao)
gdraw_glBindVertexArray(gdraw_vao);
GDrawFunctions* funcs = create_context(w, h);
if (!funcs) return NULL;
// hook the vtable entries for VBO reset and render state
real_DrawIndexedTriangles = funcs->DrawIndexedTriangles;
funcs->DrawIndexedTriangles = hooked_DrawIndexedTriangles;
real_FilterQuad = funcs->FilterQuad;
funcs->FilterQuad = hooked_FilterQuad;
real_RenderingBegin = funcs->RenderingBegin;
funcs->RenderingBegin = hooked_RenderingBegin;
funcs->ClearID = gdraw_ClearID;
gdraw->tex_formats = tex_formats;
gdraw->has_mapbuffer = false;
gdraw->has_depth24 = true;
gdraw->has_texture_max_level = true;
gdraw->has_packed_depth_stencil = true;
GLint n = 0;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &n);
gdraw->has_conditional_non_power_of_two = (n < 8192);
if (msaa_samples > 1) {
glGetIntegerv(GL_MAX_SAMPLES, &n);
gdraw->multisampling = RR_MIN(msaa_samples, n);
}
opengl_check();
fprintf(stderr, "[GDraw] Context created successfully (%dx%d, msaa=%d)\n",
w, h, msaa_samples);
return funcs;
}
// Custom draw callbacks
void gdraw_GL_BeginCustomDraw_4J(IggyCustomDrawCallbackRegion* region,
F32* matrix) {
// rebind vbo
if (gdraw_glBindVertexArray && gdraw_vao)
gdraw_glBindVertexArray(gdraw_vao);
clear_renderstate();
gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection,
depth_from_id(0), 0);
}
void gdraw_GL_CalculateCustomDraw_4J(IggyCustomDrawCallbackRegion* region,
F32* matrix) {
gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection, 0.0f, 0);
}

View file

@ -1,7 +1,9 @@
#ifndef __RAD_INCLUDE_GDRAW_SDL_H__
#define __RAD_INCLUDE_GDRAW_SDL_H__
#ifndef __LINUX_IGGY_GDRAW_H__
#define __LINUX_IGGY_GDRAW_H__
#include "../../../Windows64/Iggy/include/gdraw.h"
#include "../../../Windows64/Iggy/include/iggy.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -34,4 +36,5 @@ extern void gdraw_GL_DestroyTextureFromResource(GDrawTexture *tex);
#ifdef __cplusplus
}
#endif
#endif // __RAD_INCLUDE_GDRAW_SDL_H__
#endif // __LINUX_IGGY_GDRAW_H__

View file

@ -1,240 +0,0 @@
// Rewrite of gdraw_GLFW to gdraw_SDL
// I hope iggy gets fully implemented rrlllly quickly <3
#define GDRAW_ASSERTS
#include "../../../Windows64/Iggy/include/iggy.h"
#include "../../../Windows64/Iggy/include/gdraw.h"
#include "gdraw_sdl.h"
#include <GL/gl.h>
#include <GL/glext.h>
#include <SDL2/SDL.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#define true 1
#define false 0
// Say hi to sdl
#ifndef _ENABLEIGGY
void *IggyGDrawMallocAnnotated(SINTa size, const char *file, int line)
{
(void)file; (void)line;
return malloc((size_t)size);
}
void IggyGDrawFree(void *ptr)
{
free(ptr);
}
void IggyGDrawSendWarning(Iggy *f, char const *message, ...)
{
(void)f;
va_list args;
va_start(args, message);
fprintf(stderr, "[Iggy GDraw Warning] ");
vfprintf(stderr, message, args);
fprintf(stderr, "\n");
va_end(args);
}
void IggyDiscardVertexBufferCallback(void *owner, void *buf)
{
(void)owner; (void)buf;
}
#endif
// glActiveTexture and glCompressedTexImage2D are core GL 1.3+ on Linux and
// are declared directly in <GL/gl.h>, so they are omitted from this list.
#define GDRAW_GL_EXTENSION_LIST \
/* identifier import procname */ \
/* GL_ARB_vertex_buffer_object */ \
GLE(GenBuffers, "GenBuffersARB", GENBUFFERSARB) \
GLE(DeleteBuffers, "DeleteBuffersARB", DELETEBUFFERSARB) \
GLE(BindBuffer, "BindBufferARB", BINDBUFFERARB) \
GLE(BufferData, "BufferDataARB", BUFFERDATAARB) \
GLE(MapBuffer, "MapBufferARB", MAPBUFFERARB) \
GLE(UnmapBuffer, "UnmapBufferARB", UNMAPBUFFERARB) \
GLE(VertexAttribPointer, "VertexAttribPointerARB", VERTEXATTRIBPOINTERARB) \
GLE(EnableVertexAttribArray, "EnableVertexAttribArrayARB", ENABLEVERTEXATTRIBARRAYARB) \
GLE(DisableVertexAttribArray, "DisableVertexAttribArrayARB", DISABLEVERTEXATTRIBARRAYARB) \
/* GL_ARB_shader_objects */ \
GLE(CreateShader, "CreateShaderObjectARB", CREATESHADEROBJECTARB) \
GLE(DeleteShader, "DeleteObjectARB", DELETEOBJECTARB) \
GLE(ShaderSource, "ShaderSourceARB", SHADERSOURCEARB) \
GLE(CompileShader, "CompileShaderARB", COMPILESHADERARB) \
GLE(GetShaderiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
GLE(GetShaderInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
GLE(CreateProgram, "CreateProgramObjectARB", CREATEPROGRAMOBJECTARB) \
GLE(DeleteProgram, "DeleteObjectARB", DELETEOBJECTARB) \
GLE(AttachShader, "AttachObjectARB", ATTACHOBJECTARB) \
GLE(LinkProgram, "LinkProgramARB", LINKPROGRAMARB) \
GLE(GetUniformLocation, "GetUniformLocationARB", GETUNIFORMLOCATIONARB) \
GLE(UseProgram, "UseProgramObjectARB", USEPROGRAMOBJECTARB) \
GLE(GetProgramiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
GLE(GetProgramInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
GLE(Uniform1i, "Uniform1iARB", UNIFORM1IARB) \
GLE(Uniform4f, "Uniform4fARB", UNIFORM4FARB) \
GLE(Uniform4fv, "Uniform4fvARB", UNIFORM4FVARB) \
/* GL_ARB_vertex_shader */ \
GLE(BindAttribLocation, "BindAttribLocationARB", BINDATTRIBLOCATIONARB) \
/* Missing from WGL but needed by shared code */ \
GLE(Uniform1f, "Uniform1fARB", UNIFORM1FARB) \
/* GL_EXT_framebuffer_object */ \
GLE(GenRenderbuffers, "GenRenderbuffersEXT", GENRENDERBUFFERSEXT) \
GLE(DeleteRenderbuffers, "DeleteRenderbuffersEXT", DELETERENDERBUFFERSEXT) \
GLE(BindRenderbuffer, "BindRenderbufferEXT", BINDRENDERBUFFEREXT) \
GLE(RenderbufferStorage, "RenderbufferStorageEXT", RENDERBUFFERSTORAGEEXT) \
GLE(GenFramebuffers, "GenFramebuffersEXT", GENFRAMEBUFFERSEXT) \
GLE(DeleteFramebuffers, "DeleteFramebuffersEXT", DELETEFRAMEBUFFERSEXT) \
GLE(BindFramebuffer, "BindFramebufferEXT", BINDFRAMEBUFFEREXT) \
GLE(CheckFramebufferStatus, "CheckFramebufferStatusEXT", CHECKFRAMEBUFFERSTATUSEXT) \
GLE(FramebufferRenderbuffer, "FramebufferRenderbufferEXT", FRAMEBUFFERRENDERBUFFEREXT) \
GLE(FramebufferTexture2D, "FramebufferTexture2DEXT", FRAMEBUFFERTEXTURE2DEXT) \
GLE(GenerateMipmap, "GenerateMipmapEXT", GENERATEMIPMAPEXT) \
/* GL_EXT_framebuffer_blit */ \
GLE(BlitFramebuffer, "BlitFramebufferEXT", BLITFRAMEBUFFEREXT) \
/* GL_EXT_framebuffer_multisample */ \
GLE(RenderbufferStorageMultisample, "RenderbufferStorageMultisampleEXT",RENDERBUFFERSTORAGEMULTISAMPLEEXT) \
/* <end> */
#define gdraw_GLx_(id) gdraw_GL_##id
#define GDRAW_GLx_(id) GDRAW_GL_##id
#define GDRAW_SHADERS "gdraw_gl_shaders.inl"
// On Linux, GLhandleARB is void* but shader functions use GLuint values.
// Use GLuint as our handle type, matching the Mac pattern from gdraw_gl_shared.inl.
#define GDrawGLProgram GLuint
typedef GLuint GLhandle;
typedef gdraw_gl_resourcetype gdraw_resourcetype;
// Declare extension function pointers
#define GLE(id, import, procname) static PFNGL##procname##PROC gl##id;
GDRAW_GL_EXTENSION_LIST
#undef GLE
static void load_extensions(void)
{
#define GLE(id, import, procname) \
gl##id = (PFNGL##procname##PROC) SDL_GL_GetProcAddress("gl" import);
GDRAW_GL_EXTENSION_LIST
#undef GLE
}
static void clear_renderstate_platform_specific(void)
{
glDisable(GL_ALPHA_TEST);
}
static void error_msg_platform_specific(const char *msg)
{
fprintf(stderr, "[GDraw SDL] %s\n", msg);
}
#define GDRAW_MULTISAMPLING
// Suppress SIGTRAP from GL debug assertions on Linux
#ifdef RR_BREAK
#undef RR_BREAK
#endif
#define RR_BREAK() \
do { fprintf(stderr, "[GDraw] RR_BREAK suppressed (GL error)\n"); } while(0)
#include "../../../Windows64/Iggy/gdraw/gdraw_gl_shared.inl"
// Context creation and management
GDrawFunctions *gdraw_GL_CreateContext(S32 w, S32 h, S32 msaa_samples)
{
static const TextureFormatDesc tex_formats[] = {
{ IFT_FORMAT_rgba_8888, 1, 1, 4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_rgba_4444_LE, 1, 1, 2, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
{ IFT_FORMAT_rgba_5551_LE, 1, 1, 2, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
{ IFT_FORMAT_la_88, 1, 1, 2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_la_44, 1, 1, 1, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_i_8, 1, 1, 1, GL_INTENSITY8, GL_ALPHA, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_i_4, 1, 1, 1, GL_INTENSITY4, GL_ALPHA, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_l_8, 1, 1, 1, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_l_4, 1, 1, 1, GL_LUMINANCE4, GL_LUMINANCE, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_DXT1, 4, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_DXT3, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0, GL_UNSIGNED_BYTE },
{ IFT_FORMAT_DXT5, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0, GL_UNSIGNED_BYTE },
{ 0, 0, 0, 0, 0, 0, 0 },
};
GDrawFunctions *funcs;
const char *s;
GLint n;
// A current SDL2 GL context must be active before calling this, if it doesn't exist, just throw an warning-
s = (const char *) glGetString(GL_EXTENSIONS);
if (!s) {
fprintf(stderr, "[GDraw SDL] glGetString(GL_EXTENSIONS) returned NULL - "
"SDL GL context not current?\n");
assert(s != NULL);
return NULL;
}
// Verify required extensions
if (!hasext(s, "GL_ARB_multitexture") ||
!hasext(s, "GL_ARB_texture_compression") ||
!hasext(s, "GL_ARB_texture_mirrored_repeat") ||
!hasext(s, "GL_ARB_texture_non_power_of_two") ||
!hasext(s, "GL_ARB_vertex_buffer_object") ||
!hasext(s, "GL_EXT_framebuffer_object") ||
!hasext(s, "GL_ARB_shader_objects") ||
!hasext(s, "GL_ARB_vertex_shader") ||
!hasext(s, "GL_ARB_fragment_shader"))
{
fprintf(stderr, "[GDraw SDL] Required GL extensions not available\n");
return NULL;
}
if (!hasext(s, "GL_EXT_framebuffer_multisample") && msaa_samples > 1)
return NULL;
load_extensions();
funcs = create_context(w, h);
if (!funcs)
return NULL;
gdraw->tex_formats = tex_formats;
gdraw->has_mapbuffer = true; // core in ARB_vertex_buffer_object
gdraw->has_depth24 = true;
gdraw->has_texture_max_level = true; // core GL
if (hasext(s, "GL_EXT_packed_depth_stencil"))
gdraw->has_packed_depth_stencil = true;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &n);
gdraw->has_conditional_non_power_of_two = (n < 8192);
if (msaa_samples > 1) {
glGetIntegerv(GL_MAX_SAMPLES, &n);
gdraw->multisampling = RR_MIN(msaa_samples, n);
}
opengl_check();
fprintf(stderr, "[GDraw SDL] Context created successfully (%dx%d, msaa=%d)\n",
w, h, msaa_samples);
return funcs;
}
void gdraw_GL_BeginCustomDraw_4J(IggyCustomDrawCallbackRegion *region, F32 *matrix)
{
clear_renderstate();
gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection, depth_from_id(0), 0);
}
void gdraw_GL_CalculateCustomDraw_4J(IggyCustomDrawCallbackRegion *region, F32 *matrix)
{
gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection, 0.0f, 0);
}

View file

@ -1,135 +1,113 @@
#ifdef __linux__
#include "../stdafx.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <dlfcn.h>
#include "4J_Render.h"
#include "../../Minecraft.World/IO/Streams/IntBuffer.h"
#include "../../Minecraft.World/IO/Streams/FloatBuffer.h"
#include "../../Minecraft.World/IO/Streams/ByteBuffer.h"
void LinuxGLLogLightmapState(const char* stage, int textureId, bool scaleLight) {
static int logCount = 0;
if (logCount >= 16) return;
extern C4JRender RenderManager;
++logCount;
#ifdef GLES
extern "C" {
extern void glClearDepthf(float depth);
void glClearDepth(double depth) { glClearDepthf((float)depth); }
void glTexGeni(unsigned int, unsigned int, int) {}
void glTexGenfv(unsigned int, unsigned int, const float*) {}
void glTexCoordPointer(int, unsigned int, int, const void*) {}
void glNormalPointer(unsigned int, int, const void*) {}
void glColorPointer(int, unsigned int, int, const void*) {}
void glVertexPointer(int, unsigned int, int, const void*) {}
void glEndList(void) {}
void glCallLists(int, unsigned int, const void*) {}
}
#endif
static bool loggedSymbols = false;
if (!loggedSymbols) {
loggedSymbols = true;
app.DebugPrintf(
"[linux-lightmap] linuxgl symbols glActiveTexture=%p "
"glClientActiveTexture=%p glMultiTexCoord2f=%p\n",
reinterpret_cast<void*>(::glActiveTexture),
reinterpret_cast<void*>(::glClientActiveTexture),
reinterpret_cast<void*>(::glMultiTexCoord2f));
inline int* getIntPtr(IntBuffer* buf) {
return buf ? (int*)buf->getBuffer() + buf->position() : nullptr;
}
inline void* getBytePtr(ByteBuffer* buf) {
return buf ? (char*)buf->getBuffer() + buf->position() : nullptr;
}
void glGenTextures_4J(IntBuffer* buf) {
if (!buf) return;
int n = buf->limit() - buf->position();
int* dst = getIntPtr(buf);
for (int i = 0; i < n; i++) dst[i] = RenderManager.TextureCreate();
}
void glDeleteTextures_4J(IntBuffer* buf) {
if (!buf) return;
int n = buf->limit() - buf->position();
int* src = getIntPtr(buf);
for (int i = 0; i < n; i++) RenderManager.TextureFree(src[i]);
}
void glTexImage2D_4J(int target, int level, int internalformat, int width,
int height, int border, int format, int type,
ByteBuffer* pixels) {
(void)target;
(void)internalformat;
(void)border;
(void)format;
(void)type;
RenderManager.TextureData(width, height, getBytePtr(pixels), level,
C4JRender::TEXTURE_FORMAT_RxGyBzAw);
}
void glLight_4J(int light, int pname, FloatBuffer* params) {
const float* p = params->_getDataPointer();
int idx = (light == 0x4001) ? 1 : 0;
if (pname == 0x1203)
RenderManager.StateSetLightDirection(idx, p[0], p[1], p[2]);
else if (pname == 0x1201)
RenderManager.StateSetLightColour(idx, p[0], p[1], p[2]);
else if (pname == 0x1200)
RenderManager.StateSetLightAmbientColour(p[0], p[1], p[2]);
}
void glLightModel_4J(int pname, FloatBuffer* params) {
if (pname == 0x0B53) {
const float* p = params->_getDataPointer();
RenderManager.StateSetLightAmbientColour(p[0], p[1], p[2]);
}
GLint activeTexture = 0;
GLint matrixMode = 0;
::glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
::glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
const GLint restoreTexture = activeTexture;
::glActiveTexture(GL_TEXTURE1);
GLint unit1Binding = 0;
::glGetIntegerv(GL_TEXTURE_BINDING_2D, &unit1Binding);
const bool unit1Enabled = (::glIsEnabled(GL_TEXTURE_2D) == GL_TRUE);
GLfloat textureMatrix[16];
::glGetFloatv(GL_TEXTURE_MATRIX, textureMatrix);
::glActiveTexture(restoreTexture);
app.DebugPrintf(
"[linux-lightmap] %s tex=%d scale=%d active=%#x matrixMode=%#x "
"unit1Bound=%d unit1Enabled=%d texMatrix=[%.4f %.4f %.4f %.4f]\n",
stage, textureId, scaleLight ? 1 : 0, activeTexture, matrixMode,
unit1Binding, unit1Enabled ? 1 : 0, textureMatrix[0], textureMatrix[5],
textureMatrix[12], textureMatrix[13]);
}
int glGenTextures() {
GLuint id = 0;
::glGenTextures(1, &id);
return (int)id;
void glFog_4J(int pname, FloatBuffer* params) {
const float* p = params->_getDataPointer();
if (pname == 0x0B66) RenderManager.StateSetFogColour(p[0], p[1], p[2]);
}
void glGenTextures(IntBuffer* buf) {
GLuint id = 0;
::glGenTextures(1, &id);
buf->put((int)id);
buf->flip();
void glGetFloat_4J(int pname, FloatBuffer* params) {
const float* m = RenderManager.MatrixGet(pname);
if (m) memcpy(params->_getDataPointer(), m, 16 * sizeof(float));
}
void glDeleteTextures(int id) {
GLuint uid = (GLuint)id;
::glDeleteTextures(1, &uid);
}
void glDeleteTextures(IntBuffer* buf) {
int id = buf->get(0);
GLuint uid = (GLuint)id;
::glDeleteTextures(1, &uid);
}
void glLight(int light, int pname, FloatBuffer* params) {
::glLightfv((GLenum)light, (GLenum)pname, params->_getDataPointer());
}
void glLightModel(int pname, FloatBuffer* params) {
::glLightModelfv((GLenum)pname, params->_getDataPointer());
}
void glGetFloat(int pname, FloatBuffer* params) {
::glGetFloatv((GLenum)pname, params->_getDataPointer());
}
void glTexGen(int coord, int pname, FloatBuffer* params) {
::glTexGenfv((GLenum)coord, (GLenum)pname, params->_getDataPointer());
}
void glFog(int pname, FloatBuffer* params) {
::glFogfv((GLenum)pname, params->_getDataPointer());
}
void glTexCoordPointer(int size, int type, FloatBuffer* pointer) {
::glTexCoordPointer(size, (GLenum)type, 0, pointer->_getDataPointer());
}
void glNormalPointer(int type, ByteBuffer* pointer) {
::glNormalPointer((GLenum)type, 0, pointer->getBuffer());
}
void glColorPointer(int size, bool normalized, int stride,
ByteBuffer* pointer) {
(void)normalized;
::glColorPointer(size, GL_UNSIGNED_BYTE, stride, pointer->getBuffer());
}
void glVertexPointer(int size, int type, FloatBuffer* pointer) {
::glVertexPointer(size, (GLenum)type, 0, pointer->_getDataPointer());
}
void glEndList(int) { ::glEndList(); }
void glTexImage2D(int target, int level, int internalformat, int width,
int height, int border, int format, int type,
ByteBuffer* pixels) {
void* data = pixels ? pixels->getBuffer() : nullptr;
::glTexImage2D((GLenum)target, level, internalformat, width, height, border,
(GLenum)format, (GLenum)type, data);
}
void glCallLists(IntBuffer* lists) {
void glCallLists_4J(IntBuffer* lists) {
if (!lists) return;
int count = lists->limit() - lists->position();
::glCallLists(count, GL_INT, lists->getBuffer());
int* ids = getIntPtr(lists);
for (int i = 0; i < count; i++) RenderManager.CBuffCall(ids[i], false);
}
void glReadPixels_4J(int x, int y, int w, int h, int f, int t, ByteBuffer* p) {
(void)f;
(void)t;
RenderManager.ReadPixels(x, y, w, h, getBytePtr(p));
}
// dead stubs
void glTexCoordPointer_4J(int, int, FloatBuffer*) {}
void glNormalPointer_4J(int, ByteBuffer*) {}
void glColorPointer_4J(int, bool, int, ByteBuffer*) {}
void glVertexPointer_4J(int, int, FloatBuffer*) {}
void glEndList_4J(int) {}
void glTexGen_4J(int, int, FloatBuffer*) {}
// query objects
#include <dlfcn.h>
static PFNGLGENQUERIESARBPROC _glGenQueriesARB = nullptr;
static PFNGLBEGINQUERYARBPROC _glBeginQueryARB = nullptr;
static PFNGLENDQUERYARBPROC _glEndQueryARB = nullptr;
@ -148,40 +126,41 @@ static void initQueryFuncs() {
RTLD_DEFAULT, "glGetQueryObjectuivARB");
}
void glGenQueriesARB(IntBuffer* buf) {
void glGenQueriesARB_4J(IntBuffer* buf) {
initQueryFuncs();
if (_glGenQueriesARB) {
GLuint id = 0;
_glGenQueriesARB(1, &id);
buf->put((int)id);
buf->flip();
if (_glGenQueriesARB && buf) {
int n = buf->limit() - buf->position();
if (n > 0) _glGenQueriesARB(n, (GLuint*)getIntPtr(buf));
}
}
void glBeginQueryARB(int target, int id) {
void glBeginQueryARB_4J(int target, int id) {
initQueryFuncs();
if (_glBeginQueryARB) _glBeginQueryARB((GLenum)target, (GLuint)id);
}
void glEndQueryARB(int target) {
void glEndQueryARB_4J(int target) {
initQueryFuncs();
if (_glEndQueryARB) _glEndQueryARB((GLenum)target);
}
void glGetQueryObjectuARB(int id, int pname, IntBuffer* params) {
void glGetQueryObjectuARB_4J(int id, int pname, IntBuffer* params) {
initQueryFuncs();
if (_glGetQueryObjectuivARB) {
GLuint val = 0;
_glGetQueryObjectuivARB((GLuint)id, (GLenum)pname, &val);
params->put((int)val);
params->flip();
}
if (_glGetQueryObjectuivARB && params)
// LWJGL does not change limits/positions during these calls, it
// reads/writes exactly at pointer!!
_glGetQueryObjectuivARB((GLuint)id, (GLenum)pname,
(GLuint*)getIntPtr(params));
}
void glReadPixels(int x, int y, int width, int height, int format, int type,
ByteBuffer* pixels) {
::glReadPixels(x, y, width, height, (GLenum)format, (GLenum)type,
pixels->getBuffer());
void glGetFloat(int pname, FloatBuffer* params) {
glGetFloat_4J(pname, params);
}
#endif
void LinuxGLLogLightmapState(const char* stage, int textureId,
bool scaleLight) {
static int logCount = 0;
if (logCount >= 16) return;
++logCount;
fprintf(stderr, "[linux-lightmap] %s tex=%d scale=%d\n", stage, textureId,
scaleLight ? 1 : 0);
}
#endif

View file

@ -1,12 +1,8 @@
#include "../../../Minecraft.World/Platform/stdafx.h"
#include "Linux_UIController.h"
// Temp
#include "../../Minecraft.h"
#include "../../Textures/Textures.h"
// GDraw GL backend for Linux
#include "Iggy/gdraw/gdraw_sdl.h"
#include "Iggy/gdraw/gdraw.h"
ConsoleUIController ui;
@ -22,14 +18,12 @@ static void restoreFixedFunctionStateAfterIggy() {
glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
@ -54,7 +48,7 @@ void ConsoleUIController::init(S32 w, S32 h) {
gdraw_GL_SetResourceLimits(GDRAW_GL_RESOURCE_texture, 5000,
128 * 1024 * 1024);
gdraw_GL_SetResourceLimits(GDRAW_GL_RESOURCE_rendertarget, 10,
32 * 1024 * 1024);
64 * 1024 * 1024);
IggySetGDraw(gdraw_funcs);
#endif

View file

@ -254,6 +254,14 @@ RADEXPFUNC inline void* RADEXPLINK IggyPerfmonCreate(
}
RADEXPFUNC inline void RADEXPLINK IggyInstallPerfmon(void* perfmon) { STUBBED; }
RADEXPFUNC inline IggyResult RADEXPLINK IggyValueGetTypeRS(IggyValuePath* var,
IggyName sub_name,
char const* sub_name_utf8,
IggyDatatype* result) {
STUBBED;
return IGGY_RESULT_SUCCESS;
}
// GDraw memory/warning functions are defined in gdraw_glfw.c (C linkage)
// Juicey you stupid idiot do NOT define them here

View file

@ -57,6 +57,10 @@ static RADINLINE void break_on_err(GLint e)
#endif
}
#ifndef GDRAW_PLATFORM_REPORT_GL_SITE
#define GDRAW_PLATFORM_REPORT_GL_SITE(site) ((void)0)
#endif
static void report_err(GLint e)
{
break_on_err(e);
@ -74,17 +78,31 @@ static void eat_gl_err(void)
while (glGetError() != GL_NO_ERROR);
}
static void opengl_check_site(const char *site);
static void opengl_check(void)
{
opengl_check_site(NULL);
}
static void opengl_check_site(const char *site)
{
#ifdef _DEBUG
GLint e = glGetError();
if (e != GL_NO_ERROR) {
GDRAW_PLATFORM_REPORT_GL_SITE(site);
report_err(e);
eat_gl_err();
}
#else
(void) site;
#endif
}
#ifndef OPENGL_CHECK_SITE
#define OPENGL_CHECK_SITE(site) opengl_check_site(site)
#endif
static U32 is_pow2(S32 n)
{
return ((U32) n & (U32) (n-1)) == 0;
@ -635,6 +653,90 @@ static void RADLINK gdraw_DescribeVertexBuffer(GDrawVertexBuffer *vbuf, GDraw_Ve
// Create/free (or cache) render targets
//
#ifdef __linux__
typedef struct
{
S32 free_count;
S32 live_count;
S32 locked_count;
S32 dead_count;
S32 pinned_count;
S32 user_owned_count;
S32 alloc_count;
} GDrawHandleStateCounts;
enum
{
GDRAW_RT_DIAG_color_memory = 1 << 0,
GDRAW_RT_DIAG_color_handles = 1 << 1,
GDRAW_RT_DIAG_cache_bitmap = 1 << 2,
GDRAW_RT_DIAG_stack_depth = 1 << 3,
GDRAW_RT_DIAG_empty_request = 1 << 4,
};
static U32 gdraw_rt_diag_emitted = 0;
static void gdraw_CountHandleStates(GDrawHandleCache *cache,
GDrawHandleStateCounts *counts)
{
S32 i;
counts->free_count = 0;
counts->live_count = 0;
counts->locked_count = 0;
counts->dead_count = 0;
counts->pinned_count = 0;
counts->user_owned_count = 0;
counts->alloc_count = 0;
if (!cache)
return;
for (i = 0; i < cache->max_handles; ++i) {
switch (cache->handle[i].state) {
case GDRAW_HANDLE_STATE_free: ++counts->free_count; break;
case GDRAW_HANDLE_STATE_live: ++counts->live_count; break;
case GDRAW_HANDLE_STATE_locked: ++counts->locked_count; break;
case GDRAW_HANDLE_STATE_dead: ++counts->dead_count; break;
case GDRAW_HANDLE_STATE_pinned: ++counts->pinned_count; break;
case GDRAW_HANDLE_STATE_user_owned: ++counts->user_owned_count; break;
case GDRAW_HANDLE_STATE_alloc: ++counts->alloc_count; break;
default: break;
}
}
}
static void gdraw_ReportHandleCacheDiag(char const *label,
GDrawHandleCache *cache,
U32 once_bit,
S32 req_w,
S32 req_h)
{
GDrawHandleStateCounts counts;
if (gdraw_rt_diag_emitted & once_bit)
return;
gdraw_rt_diag_emitted |= once_bit;
gdraw_CountHandleStates(cache, &counts);
IggyGDrawSendWarning(NULL,
"GDraw[%s] diag: frame=%dx%d tile=%dx%d padded=%dx%d req=%dx%d depth=%d bytes_free=%d total_bytes=%d handles free=%d live=%d locked=%d dead=%d pinned=%d user=%d alloc=%d",
label,
gdraw->frametex_width, gdraw->frametex_height,
gdraw->tw, gdraw->th,
gdraw->tpw, gdraw->tph,
req_w, req_h,
(int) (gdraw->cur - gdraw->frame),
cache ? cache->bytes_free : 0,
cache ? cache->total_bytes : 0,
counts.free_count, counts.live_count, counts.locked_count,
counts.dead_count, counts.pinned_count, counts.user_owned_count,
counts.alloc_count);
}
#else
#define gdraw_ReportHandleCacheDiag(label, cache, once_bit, req_w, req_h) \
((void) 0)
#endif
static GDrawHandle *get_rendertarget_texture(int width, int height, void *owner, GDrawStats *gstats)
{
S32 size;
@ -678,13 +780,17 @@ static GDrawHandle *get_color_rendertarget(GDrawStats *gstats)
// ran out of RTs, allocate a new one
size = gdraw->frametex_width * gdraw->frametex_height * 4;
if (gdraw->rendertargets.bytes_free < size) {
IggyGDrawSendWarning(NULL, "GDraw exceeded available rendertarget memory");
gdraw_ReportHandleCacheDiag("rt-color-memory", &gdraw->rendertargets,
GDRAW_RT_DIAG_color_memory, gdraw->tpw, gdraw->tph);
IggyGDrawSendWarning(NULL, "GDraw[rt-color] exceeded available rendertarget memory");
return NULL;
}
t = gdraw_HandleCacheAllocateBegin(&gdraw->rendertargets);
if (!t) {
IggyGDrawSendWarning(NULL, "GDraw exceeded available rendertarget handles");
gdraw_ReportHandleCacheDiag("rt-color-handles", &gdraw->rendertargets,
GDRAW_RT_DIAG_color_handles, gdraw->tpw, gdraw->tph);
IggyGDrawSendWarning(NULL, "GDraw[rt-color] exceeded available rendertarget handles");
return t;
}
@ -992,25 +1098,31 @@ static rrbool RADLINK gdraw_TextureDrawBufferBegin(gswf_recti *region, gdraw_tex
GDrawHandle *t;
int k;
if (gdraw->tw == 0 || gdraw->th == 0) {
IggyGDrawSendWarning(NULL, "GDraw got a request for an empty rendertarget");
gdraw_ReportHandleCacheDiag("rt-empty", &gdraw->rendertargets,
GDRAW_RT_DIAG_empty_request, region->x1 - region->x0, region->y1 - region->y0);
IggyGDrawSendWarning(NULL, "GDraw[rt-stack] got a request for an empty rendertarget");
return false;
}
if (n >= &gdraw->frame[MAX_RENDER_STACK_DEPTH]) {
IggyGDrawSendWarning(NULL, "GDraw rendertarget nesting exceeded MAX_RENDER_STACK_DEPTH");
gdraw_ReportHandleCacheDiag("rt-stack-depth", &gdraw->rendertargets,
GDRAW_RT_DIAG_stack_depth, region->x1 - region->x0, region->y1 - region->y0);
IggyGDrawSendWarning(NULL, "GDraw[rt-stack] rendertarget nesting exceeded MAX_RENDER_STACK_DEPTH");
return false;
}
if (owner) {
t = get_rendertarget_texture(region->x1 - region->x0, region->y1 - region->y0, owner, gstats);
if (!t) {
IggyGDrawSendWarning(NULL, "GDraw ran out of rendertargets for cacheAsBItmap");
gdraw_ReportHandleCacheDiag("rt-cacheAsBitmap", gdraw->texturecache,
GDRAW_RT_DIAG_cache_bitmap, region->x1 - region->x0, region->y1 - region->y0);
IggyGDrawSendWarning(NULL, "GDraw[rt-cacheAsBitmap] ran out of rendertargets");
return false;
}
} else {
t = get_color_rendertarget(gstats);
if (!t) {
IggyGDrawSendWarning(NULL, "GDraw ran out of rendertargets");
IggyGDrawSendWarning(NULL, "GDraw[rt-color] ran out of rendertargets");
return false;
}
}
@ -1355,18 +1467,18 @@ static int set_render_state(GDrawRenderState *r, S32 vformat, const int **ovvars
}
use_lazy_shader(prg);
opengl_check();
OPENGL_CHECK_SITE("set_render_state:use_lazy_shader");
fvars = prg->vars[0];
vvars = prg->vars[1];
if (vformat == GDRAW_vformat_ihud1) {
F32 wv[2][4] = { 1.0f/960,0,0,-1.0, 0,-1.0f/540,0,+1.0 };
glUniform4fv(vvars[VAR_ihudv_worldview], 2, wv[0]);
opengl_check();
OPENGL_CHECK_SITE("set_render_state:ihud_worldview");
glUniform4fv(vvars[VAR_ihudv_material], p->uniform_count, p->uniforms);
opengl_check();
OPENGL_CHECK_SITE("set_render_state:ihud_material");
glUniform1f(vvars[VAR_ihudv_textmode], p->drawprim_mode ? 0.0f : 1.0f);
opengl_check();
OPENGL_CHECK_SITE("set_render_state:ihud_textmode");
} else {
// set vertex shader constants
@ -1393,7 +1505,7 @@ static int set_render_state(GDrawRenderState *r, S32 vformat, const int **ovvars
// texture stuff
set_texture(0, r->tex[0]);
opengl_check();
OPENGL_CHECK_SITE("set_render_state:set_texture0");
if (r->tex[0] && gdraw->has_conditional_non_power_of_two && ((GDrawHandle*) r->tex[0])->handle.tex.nonpow2) {
// only wrap mode allowed in conditional nonpow2 is clamp; this should
@ -1490,7 +1602,7 @@ static int set_render_state(GDrawRenderState *r, S32 vformat, const int **ovvars
else
glDepthMask(GL_FALSE);
opengl_check();
OPENGL_CHECK_SITE("set_render_state:final");
if (ovvars)
*ovvars = vvars;
@ -1611,7 +1723,7 @@ static void RADLINK gdraw_DrawIndexedTriangles(GDrawRenderState *r, GDrawPrimiti
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
opengl_check();
OPENGL_CHECK_SITE("gdraw_DrawIndexedTriangles:final");
tag_resources(vb, r->tex[0], r->tex[1]);
}
@ -1628,33 +1740,33 @@ static void do_screen_quad(gswf_recti *s, F32 *tc, const int *vvars, GDrawStats
F32 vert[4][4];
F32 world[2*4];
opengl_check();
OPENGL_CHECK_SITE("do_screen_quad:begin");
vert[0][0] = px0; vert[0][1] = py0; vert[0][2] = s0; vert[0][3] = t0;
vert[1][0] = px1; vert[1][1] = py0; vert[1][2] = s1; vert[1][3] = t0;
vert[2][0] = px1; vert[2][1] = py1; vert[2][2] = s1; vert[2][3] = t1;
vert[3][0] = px0; vert[3][1] = py1; vert[3][2] = s0; vert[3][3] = t1;
opengl_check();
OPENGL_CHECK_SITE("do_screen_quad:after_vertices");
gdraw_PixelSpace(world);
world[2] = depth;
set_world_projection(vvars, world);
opengl_check();
OPENGL_CHECK_SITE("do_screen_quad:after_projection");
set_vertex_format(GDRAW_vformat_v2tc2, vert[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
opengl_check();
OPENGL_CHECK_SITE("do_screen_quad:before_draw");
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
reset_vertex_format(GDRAW_vformat_v2tc2);
opengl_check();
OPENGL_CHECK_SITE("do_screen_quad:after_draw");
gstats->nonzero_flags |= GDRAW_STATS_batches;
gstats->num_batches += 1;
gstats->drawn_vertices += 4;
gstats->drawn_indices += 6;
opengl_check();
OPENGL_CHECK_SITE("do_screen_quad:final");
}
#ifdef GDRAW_FEWER_CLEARS
@ -1805,7 +1917,7 @@ static void RADLINK gdraw_FilterQuad(GDrawRenderState *r, S32 x0, S32 y0, S32 x1
glColorMask(1,1,1,1);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
opengl_check();
OPENGL_CHECK_SITE("gdraw_FilterQuad:pre_filter");
if (r->blend_mode == GDRAW_BLEND_filter) {
switch (r->filter) {

View file

@ -5,8 +5,8 @@
#pragma once
//#include <xtl.h>
//#include <xboxmath.h>
// #include <xtl.h>
// #include <xboxmath.h>
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
@ -34,7 +34,7 @@
#include <kernel.h>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <vector>
#include <fios2.h>
#include <message_dialog.h>
#include <game_live_streaming.h>
@ -49,7 +49,7 @@
#include <kernel.h>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <vector>
#include <touch.h>
#include "../Platform/PSVita/PSVitaExtras/PSVitaTypes.h"
#include "../Platform/PSVita/PSVitaExtras/PSVitaStubs.h"
@ -71,8 +71,8 @@
typedef unsigned __int64 __uint64;
#endif
#ifdef _WINDOWS64
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#ifdef _WINDOWS64
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <malloc.h>
@ -80,14 +80,12 @@ typedef unsigned __int64 __uint64;
// TODO: reference additional headers your program requires here
#include <d3d11.h>
#include <DirectXMath.h>
using namespace DirectX;
using namespace DirectX;
#define HRESULT_SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#endif
#ifdef _DURANGO
#include <xdk.h>
#include <wrl.h>
@ -95,14 +93,12 @@ using namespace DirectX;
#include <DirectXMath.h>
#include <ppltasks.h>
#include <collection.h>
using namespace DirectX;
using namespace DirectX;
#include <pix.h>
#include "../Platform/Durango/DurangoExtras/DurangoStubs.h"
#define HRESULT_SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#endif
#ifdef _XBOX
#include <xtl.h>
#include <xboxmath.h>
@ -166,42 +162,42 @@ typedef XUID GameSessionUID;
#include "../../Minecraft.World/Util/PerformanceTimer.h"
#ifdef _XBOX
#include "xbox/4JLibs/inc/4J_Input.h"
#include "xbox/4JLibs/inc/4J_Profile.h"
#include "xbox/4JLibs/inc/4J_Render.h"
#include "xbox/4JLibs/inc/4J_XTMS.h"
#include "xbox/4JLibs/inc/4J_Storage.h"
#elif defined (__PS3__)
#include "xbox/4JLibs/inc/4J_Input.h"
#include "xbox/4JLibs/inc/4J_Profile.h"
#include "xbox/4JLibs/inc/4J_Render.h"
#include "xbox/4JLibs/inc/4J_XTMS.h"
#include "xbox/4JLibs/inc/4J_Storage.h"
#elif defined(__PS3__)
#include "../Platform/PS3/4JLibs/inc/4J_Input.h"
#include "../Platform/PS3/4JLibs/inc/4J_Profile.h"
#include "../Platform/PS3/4JLibs/inc/4J_Render.h"
#include "../Platform/PS3/4JLibs/inc/4J_Storage.h"
#include "../Platform/PS3/4JLibs/inc/4J_Input.h"
#include "../Platform/PS3/4JLibs/inc/4J_Profile.h"
#include "../Platform/PS3/4JLibs/inc/4J_Render.h"
#include "../Platform/PS3/4JLibs/inc/4J_Storage.h"
#elif defined _DURANGO
#include "../Platform/Durango/4JLibs/inc/4J_Input.h"
#include "../Platform/Durango/4JLibs/inc/4J_Profile.h"
#include "../Platform/Durango/4JLibs/inc/4J_Render.h"
#include "../Platform/Durango/4JLibs/inc/4J_Storage.h"
#include "../Platform/Durango/4JLibs/inc/4J_Input.h"
#include "../Platform/Durango/4JLibs/inc/4J_Profile.h"
#include "../Platform/Durango/4JLibs/inc/4J_Render.h"
#include "../Platform/Durango/4JLibs/inc/4J_Storage.h"
#elif defined _WINDOWS64
#include "../Platform/Windows64/4JLibs/inc/4J_Input.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Profile.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Render.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Storage.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Input.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Profile.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Render.h"
#include "../Platform/Windows64/4JLibs/inc/4J_Storage.h"
#elif defined __linux__
#include "4J_Input.h"
#include "4J_Profile.h"
#include "4J_Render.h"
#include "4J_Storage.h"
#include "4J_Input.h"
#include "4J_Profile.h"
#include "4J_Render.h"
#include "4J_Storage.h"
#elif defined __PSVITA__
#include "../Platform/PSVita/4JLibs/inc/4J_Input.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Profile.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Render.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Storage.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Input.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Profile.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Render.h"
#include "../Platform/PSVita/4JLibs/inc/4J_Storage.h"
#else
#include "../Platform/Orbis/4JLibs/inc/4J_Input.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Profile.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Render.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Storage.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Input.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Profile.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Render.h"
#include "../Platform/Orbis/4JLibs/inc/4J_Storage.h"
#endif
#include "../Textures/Textures.h"
@ -229,7 +225,7 @@ typedef XUID GameSessionUID;
#include "../Platform/Common/App_enums.h"
#include "../Platform/Common/Tutorial/TutorialEnum.h"
#include "../Platform/Common/App_structs.h"
//#endif
// #endif
#include "../Platform/Common/Consoles_App.h"
#include "../Platform/Common/Minecraft_Macros.h"
@ -242,95 +238,94 @@ typedef XUID GameSessionUID;
#include "strings.h"
#ifdef _XBOX
#include "../Platform/Xbox/Xbox_App.h"
#include "../Platform/Xbox/Sentient/MinecraftTelemetry.h"
#include "../Platform/Xbox/Sentient/DynamicConfigurations.h"
#include "../Platform/Xbox/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Xbox/Sentient/Include/SenClientStats.h"
#include "../Platform/Xbox/GameConfig/Minecraft.spa.h"
#include "../../Minecraft.Assets/XboxMedia/4J_strings.h"
#include "../Platform/Xbox/XML/ATGXmlParser.h"
#include "../Platform/Xbox/Leaderboards/XboxLeaderboardManager.h"
#include "../Platform/Xbox/Social/SocialManager.h"
#include "../Platform/Xbox/Audio/SoundEngine.h"
#include "../Platform/Xbox/Xbox_UIController.h"
#include "../Platform/Xbox/Xbox_App.h"
#include "../Platform/Xbox/Sentient/MinecraftTelemetry.h"
#include "../Platform/Xbox/Sentient/DynamicConfigurations.h"
#include "../Platform/Xbox/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Xbox/Sentient/Include/SenClientStats.h"
#include "../Platform/Xbox/GameConfig/Minecraft.spa.h"
#include "../../Minecraft.Assets/XboxMedia/4J_strings.h"
#include "../Platform/Xbox/XML/ATGXmlParser.h"
#include "../Platform/Xbox/Leaderboards/XboxLeaderboardManager.h"
#include "../Platform/Xbox/Social/SocialManager.h"
#include "../Platform/Xbox/Audio/SoundEngine.h"
#include "../Platform/Xbox/Xbox_UIController.h"
#elif defined (__PS3__)
#include "extraX64client.h"
#include "../Platform/PS3/Sentient/MinecraftTelemetry.h"
#include "../Platform/PS3/Sentient/DynamicConfigurations.h"
#include "../Platform/PS3/Sentient/SentientTelemetryCommon.h"
#include "../Platform/PS3/PS3_App.h"
#include "../Platform/PS3/GameConfig/Minecraft.spa.h"
#include "../../Minecraft.Assets/PS3Media/4J_strings.h"
#include "../Platform/PS3/XML/ATGXmlParser.h"
#include "../Platform/PS3/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/PS3/Iggy/include/iggy.h"
#include "../Platform/PS3/Iggy/gdraw/gdraw_ps3gcm.h"
#include "../Platform/PS3/PS3_UIController.h"
#elif defined(__PS3__)
#include "extraX64client.h"
#include "../Platform/PS3/Sentient/MinecraftTelemetry.h"
#include "../Platform/PS3/Sentient/DynamicConfigurations.h"
#include "../Platform/PS3/Sentient/SentientTelemetryCommon.h"
#include "../Platform/PS3/PS3_App.h"
#include "../Platform/PS3/GameConfig/Minecraft.spa.h"
#include "../../Minecraft.Assets/PS3Media/4J_strings.h"
#include "../Platform/PS3/XML/ATGXmlParser.h"
#include "../Platform/PS3/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/PS3/Iggy/include/iggy.h"
#include "../Platform/PS3/Iggy/gdraw/gdraw_ps3gcm.h"
#include "../Platform/PS3/PS3_UIController.h"
#elif defined _DURANGO
#include "../Platform/Durango/Sentient/MinecraftTelemetry.h"
#include "../Platform/Durango/Durango_App.h"
#include "../Platform/Durango/Sentient/DynamicConfigurations.h"
#include "../Platform/Durango/Sentient/TelemetryEnum.h"
#include "../Platform/Durango/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Durango/PresenceIds.h"
#include "../../Minecraft.Assets/DurangoMedia/4J_strings.h"
#include "../Platform/Durango/XML/ATGXmlParser.h"
#include "../Platform/Durango/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Durango/Iggy/include/iggy.h"
#include "../Platform/Durango/Iggy/gdraw/gdraw_d3d11.h"
#include "../Platform/Durango/Durango_UIController.h"
#include "../Platform/Durango/Sentient/MinecraftTelemetry.h"
#include "../Platform/Durango/Durango_App.h"
#include "../Platform/Durango/Sentient/DynamicConfigurations.h"
#include "../Platform/Durango/Sentient/TelemetryEnum.h"
#include "../Platform/Durango/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Durango/PresenceIds.h"
#include "../../Minecraft.Assets/DurangoMedia/4J_strings.h"
#include "../Platform/Durango/XML/ATGXmlParser.h"
#include "../Platform/Durango/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Durango/Iggy/include/iggy.h"
#include "../Platform/Durango/Iggy/gdraw/gdraw_d3d11.h"
#include "../Platform/Durango/Durango_UIController.h"
#elif defined _WINDOWS64
#include "../Platform/Windows64/Sentient/MinecraftTelemetry.h"
#include "../Platform/Windows64/Windows64_App.h"
#include "../Platform/Windows64/Sentient/DynamicConfigurations.h"
#include "../Platform/Windows64/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Windows64/GameConfig/Minecraft.spa.h"
#include "../Platform/Windows64/XML/ATGXmlParser.h"
#include "../Platform/Windows64/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Windows64/Iggy/include/iggy.h"
#include "../Platform/Windows64/Iggy/gdraw/gdraw_d3d11.h"
#include "../Platform/Windows64/Windows64_UIController.h"
#include "../Platform/Windows64/Sentient/MinecraftTelemetry.h"
#include "../Platform/Windows64/Windows64_App.h"
#include "../Platform/Windows64/Sentient/DynamicConfigurations.h"
#include "../Platform/Windows64/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Windows64/GameConfig/Minecraft.spa.h"
#include "../Platform/Windows64/XML/ATGXmlParser.h"
#include "../Platform/Windows64/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Windows64/Iggy/include/iggy.h"
#include "../Platform/Windows64/Iggy/gdraw/gdraw_d3d11.h"
#include "../Platform/Windows64/Windows64_UIController.h"
#elif defined __linux__
// Linux build: avoid pulling in Windows64 platform headers (they cause
// symbol/class redefinitions). Use Orbis-compatible stubs and Linux controller.
#include "../Platform/Linux/Linux_App.h"
#include "../Platform/Linux/Iggy/include/iggy.h"
#include "../Platform/Linux/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Linux/Sentient/DynamicConfigurations.h"
#include "../Platform/Orbis/GameConfig/Minecraft.spa.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Linux/Linux_UIController.h"
#include "../Platform/Linux/Social/SocialManager.h"
// todo: cleanup ts
#include "../Platform/Linux/Linux_App.h"
#include "../Platform/Linux/Iggy/include/iggy.h"
#include "../Platform/Linux/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Linux/Sentient/DynamicConfigurations.h"
#include "../Platform/Orbis/GameConfig/Minecraft.spa.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Linux/Linux_UIController.h"
#include "../Platform/Linux/Social/SocialManager.h"
#elif defined __PSVITA__
#include "../Platform/PSVita/PSVita_App.h"
#include "../Platform/PSVita/Sentient/SentientManager.h"
#include "../Platform/PSVita/Sentient/MinecraftTelemetry.h"
#include "../Platform/PSVita/Sentient/DynamicConfigurations.h"
#include "../Platform/PSVita/GameConfig/Minecraft.spa.h"
#include "../Platform/PSVita/XML/ATGXmlParser.h"
#include "../Platform/PSVita/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/PSVita/Iggy/include/iggy.h"
#include "../Platform/PSVita/Iggy/gdraw/gdraw_psp2.h"
#include "../Platform/PSVita/PSVita_UIController.h"
#include "../Platform/PSVita/PSVita_App.h"
#include "../Platform/PSVita/Sentient/SentientManager.h"
#include "../Platform/PSVita/Sentient/MinecraftTelemetry.h"
#include "../Platform/PSVita/Sentient/DynamicConfigurations.h"
#include "../Platform/PSVita/GameConfig/Minecraft.spa.h"
#include "../Platform/PSVita/XML/ATGXmlParser.h"
#include "../Platform/PSVita/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/PSVita/Iggy/include/iggy.h"
#include "../Platform/PSVita/Iggy/gdraw/gdraw_psp2.h"
#include "../Platform/PSVita/PSVita_UIController.h"
#else
#include "../Platform/Orbis/Sentient/MinecraftTelemetry.h"
#include "../Platform/Orbis/Orbis_App.h"
#include "../Platform/Orbis/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Orbis/Sentient/DynamicConfigurations.h"
#include "../Platform/Orbis/GameConfig/Minecraft.spa.h"
#include "../../Minecraft.Assets/OrbisMedia/4J_strings.h"
#include "../Platform/Orbis/XML/ATGXmlParser.h"
#include "../Platform/Windows64/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Orbis/Iggy/include/iggy.h"
#include "../Platform/Orbis/Iggy/gdraw/gdraw_orbis.h"
#include "../Platform/Orbis/Orbis_UIController.h"
#include "../Platform/Orbis/Sentient/MinecraftTelemetry.h"
#include "../Platform/Orbis/Orbis_App.h"
#include "../Platform/Orbis/Sentient/SentientTelemetryCommon.h"
#include "../Platform/Orbis/Sentient/DynamicConfigurations.h"
#include "../Platform/Orbis/GameConfig/Minecraft.spa.h"
#include "../../Minecraft.Assets/OrbisMedia/4J_strings.h"
#include "../Platform/Orbis/XML/ATGXmlParser.h"
#include "../Platform/Windows64/Social/SocialManager.h"
#include "../Platform/Common/Audio/SoundEngine.h"
#include "../Platform/Orbis/Iggy/include/iggy.h"
#include "../Platform/Orbis/Iggy/gdraw/gdraw_orbis.h"
#include "../Platform/Orbis/Orbis_UIController.h"
#endif
#ifdef _XBOX
@ -358,13 +353,11 @@ typedef XUID GameSessionUID;
#include "../Platform/Common/Telemetry/TelemetryManager.h"
#ifdef _XBOX
//#include "../Platform/Xbox/Xbox_App.h"
// #include "../Platform/Xbox/Xbox_App.h"
#elif !defined(__PS3__)
#include "extraX64client.h"
#endif
#ifdef _FINAL_BUILD
#define printf BREAKTHECOMPILE
#define wprintf BREAKTHECOMPILE

View file

@ -13,30 +13,32 @@ class FloatBuffer;
class IntBuffer;
class ByteBuffer;
void glGenTextures(IntBuffer *);
void glGenTextures(IntBuffer*);
int glGenTextures();
void glDeleteTextures(IntBuffer *);
void glDeleteTextures(IntBuffer*);
void glDeleteTextures(int);
void glLight(int, int, FloatBuffer *);
void glLightModel(int, FloatBuffer *);
void glGetFloat(int, FloatBuffer *);
void glTexGen(int, int, FloatBuffer *);
void glFog(int, FloatBuffer *);
void glTexCoordPointer(int, int, FloatBuffer *);
void glNormalPointer(int, ByteBuffer *);
void glColorPointer(int, bool, int, ByteBuffer *);
void glVertexPointer(int, int, FloatBuffer *);
void glEndList(int);
void glTexImage2D(int, int, int, int, int, int, int, int, ByteBuffer *);
void glCallLists(IntBuffer *);
void glGenQueriesARB(IntBuffer *);
void glLight(int, int, FloatBuffer*);
void glLightModel(int, FloatBuffer*);
void glGetFloat(int, FloatBuffer*);
void glTexGen(int, int, FloatBuffer*);
void glFog(int, FloatBuffer*);
void glTexCoordPointer(int, int, FloatBuffer*);
void glNormalPointer(int, ByteBuffer*);
void glColorPointer(int, bool, int, ByteBuffer*);
void glVertexPointer(int, int, FloatBuffer*);
void glEndList_4J(int vertexCount = 0);
void glTexImage2D(int, int, int, int, int, int, int, int, ByteBuffer*);
void glCallLists(IntBuffer*);
void glGenQueriesARB(IntBuffer*);
void glBeginQueryARB(int, int);
void glEndQueryARB(int);
void glGetQueryObjectuARB(int, int, IntBuffer *);
void glReadPixels(int, int, int, int, int, int, ByteBuffer *);
void glGetQueryObjectuARB(int, int, IntBuffer*);
void glReadPixels(int, int, int, int, int, int, ByteBuffer*);
void LinuxGLLogLightmapState(const char* stage, int textureId, bool scaleLight);
void LinuxLogStubLightmapProbe();
#else
const int GL_BYTE = 0;
@ -54,13 +56,9 @@ const int GL_NORMALIZE = 0;
const int GL_RESCALE_NORMAL = 0;
const int GL_SMOOTH = 0;
const int GL_FLAT = 0;
const int GL_RGBA = 0;
const int GL_BGRA = 1;
const int GL_BGR = 0;
@ -83,73 +81,73 @@ const int GL_TEXTURE1 = 0;
const int GL_TEXTURE0 = 1;
void glFlush();
void glTexGeni(int,int,int);
void glTexGen(int,int,FloatBuffer *);
void glReadPixels(int,int, int, int, int, int, ByteBuffer *);
void glTexGeni(int, int, int);
void glTexGen(int, int, FloatBuffer*);
void glReadPixels(int, int, int, int, int, int, ByteBuffer*);
void glClearDepth(double);
void glCullFace(int);
void glDeleteLists(int,int);
void glGenTextures(IntBuffer *);
void glDeleteLists(int, int);
void glGenTextures(IntBuffer*);
int glGenTextures();
int glGenLists(int);
void glLight(int, int,FloatBuffer *);
void glLightModel(int, FloatBuffer *);
void glGetFloat(int a, FloatBuffer *b);
void glLight(int, int, FloatBuffer*);
void glLightModel(int, FloatBuffer*);
void glGetFloat(int a, FloatBuffer* b);
void glTexCoordPointer(int, int, int, int);
void glTexCoordPointer(int, int, FloatBuffer *);
void glTexCoordPointer(int, int, FloatBuffer*);
void glNormalPointer(int, int, int);
void glNormalPointer(int, ByteBuffer *);
void glNormalPointer(int, ByteBuffer*);
void glEnableClientState(int);
void glDisableClientState(int);
void glColorPointer(int, bool, int, ByteBuffer *);
void glColorPointer(int, bool, int, ByteBuffer*);
void glColorPointer(int, int, int, int);
void glVertexPointer(int, int, int, int);
void glVertexPointer(int, int, FloatBuffer *);
void glDrawArrays(int,int,int);
void glTranslatef(float,float,float);
void glRotatef(float,float,float,float);
void glNewList(int,int);
void glVertexPointer(int, int, FloatBuffer*);
void glDrawArrays(int, int, int);
void glTranslatef(float, float, float);
void glRotatef(float, float, float, float);
void glNewList(int, int);
void glEndList(int vertexCount = 0);
void glCallList(int);
void glPopMatrix();
void glPushMatrix();
void glColor3f(float,float,float);
void glScalef(float,float,float);
void glMultMatrixf(float *);
void glColor4f(float,float,float,float);
void glColor3f(float, float, float);
void glScalef(float, float, float);
void glMultMatrixf(float*);
void glColor4f(float, float, float, float);
void glDisable(int);
void glEnable(int);
void glBlendFunc(int,int);
void glBlendFunc(int, int);
void glDepthMask(bool);
void glNormal3f(float,float,float);
void glNormal3f(float, float, float);
void glDepthFunc(int);
void glMatrixMode(int);
void glLoadIdentity();
void glBindTexture(int,int);
void glTexParameteri(int,int,int);
void glTexImage2D(int,int,int,int,int,int,int,int,ByteBuffer *);
void glDeleteTextures(IntBuffer *);
void glBindTexture(int, int);
void glTexParameteri(int, int, int);
void glTexImage2D(int, int, int, int, int, int, int, int, ByteBuffer*);
void glDeleteTextures(IntBuffer*);
void glDeleteTextures(int);
void glCallLists(IntBuffer *);
void glGenQueriesARB(IntBuffer *);
void glColorMask(bool,bool,bool,bool);
void glBeginQueryARB(int,int);
void glCallLists(IntBuffer*);
void glGenQueriesARB(IntBuffer*);
void glColorMask(bool, bool, bool, bool);
void glBeginQueryARB(int, int);
void glEndQueryARB(int);
void glGetQueryObjectuARB(int,int,IntBuffer *);
void glGetQueryObjectuARB(int, int, IntBuffer*);
void glShadeModel(int);
void glPolygonOffset(float,float);
void glPolygonOffset(float, float);
void glLineWidth(float);
void glScaled(double,double,double);
void gluPerspective(float,float,float,float);
void glScaled(double, double, double);
void gluPerspective(float, float, float, float);
void glClear(int);
void glViewport(int,int,int,int);
void glAlphaFunc(int,float);
void glOrtho(float,float,float,float,float,float);
void glClearColor(float,float,float,float);
void glFogi(int,int);
void glFogf(int,float);
void glFog(int,FloatBuffer *);
void glColorMaterial(int,int);
void glViewport(int, int, int, int);
void glAlphaFunc(int, float);
void glOrtho(float, float, float, float, float, float);
void glClearColor(float, float, float, float);
void glFogi(int, int);
void glFogf(int, float);
void glFog(int, FloatBuffer*);
void glColorMaterial(int, int);
void glMultiTexCoord2f(int, float, float);
void glClientActiveTexture(int);
@ -158,164 +156,150 @@ void glActiveTexture(int);
#endif
#ifdef __linux__
class GL11
{
public:
static const int GL_SMOOTH = 0x1D01;
static const int GL_FLAT = 0x1D00;
static void glShadeModel(int mode) { ::glShadeModel(mode); }
};
class GL11 {
public:
static const int GL_SMOOTH = 0x1D01;
static const int GL_FLAT = 0x1D00;
#undef glShadeModel
#define GL_SHADEMODEL_IS_FUNCTION
static void glShadeModel(int mode) { ::glShadeModel(mode); }
};
#undef GL_ARRAY_BUFFER_ARB
#undef GL_STREAM_DRAW_ARB
class ARBVertexBufferObject
{
class ARBVertexBufferObject {
public:
static const int GL_ARRAY_BUFFER_ARB = 0x8892;
static const int GL_STREAM_DRAW_ARB = 0x88E0;
static void glBindBufferARB(int, int) {}
static void glBufferDataARB(int, ByteBuffer *, int) {}
static void glGenBuffersARB(IntBuffer *) {}
static const int GL_ARRAY_BUFFER_ARB = 0x8892;
static const int GL_STREAM_DRAW_ARB = 0x88E0;
static void glBindBufferARB(int, int) {}
static void glBufferDataARB(int, ByteBuffer*, int) {}
static void glGenBuffersARB(IntBuffer*) {}
};
#else
class GL11
{
class GL11 {
public:
static const int GL_SMOOTH = 0;
static const int GL_FLAT = 0;
static void glShadeModel(int) {};
static const int GL_SMOOTH = 0;
static const int GL_FLAT = 0;
static void glShadeModel(int) {};
};
class ARBVertexBufferObject
{
class ARBVertexBufferObject {
public:
static const int GL_ARRAY_BUFFER_ARB = 0;
static const int GL_STREAM_DRAW_ARB = 0;
static void glBindBufferARB(int, int) {}
static void glBufferDataARB(int, ByteBuffer *, int) {}
static void glGenBuffersARB(IntBuffer *) {}
static const int GL_ARRAY_BUFFER_ARB = 0;
static const int GL_STREAM_DRAW_ARB = 0;
static void glBindBufferARB(int, int) {}
static void glBufferDataARB(int, ByteBuffer*, int) {}
static void glGenBuffersARB(IntBuffer*) {}
};
#endif
class Level;
class Player;
class Textures;
class Font;
class MapItemSavedData;
class Mob;
class Particles
{
class Particles {
public:
void render(float) {}
void tick() {}
void render(float) {}
void tick() {}
};
class BufferedImage;
class Graphics
{
class Graphics {
public:
void drawImage(BufferedImage *, int, int, void *) {}
void dispose() {}
void drawImage(BufferedImage*, int, int, void*) {}
void dispose() {}
};
class ZipEntry
{
};
class ZipEntry {};
class InputStream;
class File;
class ZipFile
{
class ZipFile {
public:
ZipFile(File *file) {}
InputStream *getInputStream(ZipEntry *entry) { return NULL; }
ZipEntry *getEntry(const std::wstring& name) {return NULL;}
void close() {}
ZipFile(File* file) {}
InputStream* getInputStream(ZipEntry* entry) { return NULL; }
ZipEntry* getEntry(const std::wstring& name) { return NULL; }
void close() {}
};
class ImageIO
{
class ImageIO {
public:
static BufferedImage *read(InputStream *in) { return NULL; }
static BufferedImage* read(InputStream* in) { return NULL; }
};
class Keyboard
{
class Keyboard {
public:
static void create() {}
static void destroy() {}
static bool isKeyDown(int) {return false;}
static std::wstring getKeyName(int) { return L"KEYNAME"; }
static void enableRepeatEvents(bool) {}
static const int KEY_A = 0;
static const int KEY_B = 1;
static const int KEY_C = 2;
static const int KEY_D = 3;
static const int KEY_E = 4;
static const int KEY_F = 5;
static const int KEY_G = 6;
static const int KEY_H = 7;
static const int KEY_I = 8;
static const int KEY_J = 9;
static const int KEY_K = 10;
static const int KEY_L = 11;
static const int KEY_M = 12;
static const int KEY_N = 13;
static const int KEY_O = 14;
static const int KEY_P = 15;
static const int KEY_Q = 16;
static const int KEY_R = 17;
static const int KEY_S = 18;
static const int KEY_T = 19;
static const int KEY_U = 20;
static const int KEY_V = 21;
static const int KEY_W = 22;
static const int KEY_X = 23;
static const int KEY_Y = 24;
static const int KEY_Z = 25;
static const int KEY_SPACE = 26;
static const int KEY_LSHIFT = 27;
static const int KEY_ESCAPE = 28;
static const int KEY_BACK = 29;
static const int KEY_RETURN = 30;
static const int KEY_RSHIFT = 31;
static const int KEY_UP = 32;
static const int KEY_DOWN = 33;
static const int KEY_TAB = 34;
static void create() {}
static void destroy() {}
static bool isKeyDown(int) { return false; }
static std::wstring getKeyName(int) { return L"KEYNAME"; }
static void enableRepeatEvents(bool) {}
static const int KEY_A = 0;
static const int KEY_B = 1;
static const int KEY_C = 2;
static const int KEY_D = 3;
static const int KEY_E = 4;
static const int KEY_F = 5;
static const int KEY_G = 6;
static const int KEY_H = 7;
static const int KEY_I = 8;
static const int KEY_J = 9;
static const int KEY_K = 10;
static const int KEY_L = 11;
static const int KEY_M = 12;
static const int KEY_N = 13;
static const int KEY_O = 14;
static const int KEY_P = 15;
static const int KEY_Q = 16;
static const int KEY_R = 17;
static const int KEY_S = 18;
static const int KEY_T = 19;
static const int KEY_U = 20;
static const int KEY_V = 21;
static const int KEY_W = 22;
static const int KEY_X = 23;
static const int KEY_Y = 24;
static const int KEY_Z = 25;
static const int KEY_SPACE = 26;
static const int KEY_LSHIFT = 27;
static const int KEY_ESCAPE = 28;
static const int KEY_BACK = 29;
static const int KEY_RETURN = 30;
static const int KEY_RSHIFT = 31;
static const int KEY_UP = 32;
static const int KEY_DOWN = 33;
static const int KEY_TAB = 34;
};
class Mouse
{
class Mouse {
public:
static void create() {}
static void destroy() {}
static int getX() { return 0; }
static int getY() { return 0; }
static bool isButtonDown(int) { return false; }
static void create() {}
static void destroy() {}
static int getX() { return 0; }
static int getY() { return 0; }
static bool isButtonDown(int) { return false; }
};
class Display
{
class Display {
public:
static bool isActive() {return true;}
static void update();
static void swapBuffers();
static void destroy() {}
static bool isActive() { return true; }
static void update();
static void swapBuffers();
static void destroy() {}
};
class BackgroundDownloader
{
class BackgroundDownloader {
public:
BackgroundDownloader(File workDir, Minecraft* minecraft) {}
void start() {}
void halt() {}
void forceReload() {}
BackgroundDownloader(File workDir, Minecraft* minecraft) {}
void start() {}
void halt() {}
void forceReload() {}
};
class Color
{
class Color {
public:
static int HSBtoRGB(float,float,float) {return 0;}
static int HSBtoRGB(float, float, float) { return 0; }
};

View file

@ -7,6 +7,8 @@
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
#include "LevelRenderer.h"
#include "../Utils/FrameProfiler.h"
#include <unordered_set>
#ifdef __PS3__
#include "../Platform/PS3/SPU_Tasks/ChunkUpdate/ChunkRebuildData.h"
@ -35,6 +37,66 @@ Tesselator* Chunk::t = Tesselator::getInstance();
#endif
LevelRenderer* Chunk::levelRenderer;
void Chunk::reconcileRenderableTileEntities(
const std::vector<std::shared_ptr<TileEntity> >& renderableTileEntities) {
int key =
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
AUTO_VAR(it, globalRenderableTileEntities->find(key));
if (!renderableTileEntities.empty()) {
std::unordered_set<TileEntity*> currentRenderableTileEntitySet;
currentRenderableTileEntitySet.reserve(renderableTileEntities.size());
for (size_t i = 0; i < renderableTileEntities.size(); i++) {
currentRenderableTileEntitySet.insert(renderableTileEntities[i].get());
}
if (it != globalRenderableTileEntities->end()) {
LevelRenderer::RenderableTileEntityBucket& existingBucket =
it->second;
for (AUTO_VAR(it2, existingBucket.tiles.begin());
it2 != existingBucket.tiles.end(); it2++) {
TileEntity* tileEntity = (*it2).get();
if (currentRenderableTileEntitySet.find(tileEntity) ==
currentRenderableTileEntitySet.end()) {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
levelRenderer->queueRenderableTileEntityForRemoval_Locked(
key, tileEntity);
} else {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageKeep);
}
}
for (size_t i = 0; i < renderableTileEntities.size(); i++) {
renderableTileEntities[i]->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageKeep);
if (existingBucket.indexByTile.find(renderableTileEntities[i].get()) ==
existingBucket.indexByTile.end()) {
levelRenderer->addRenderableTileEntity_Locked(
key, renderableTileEntities[i]);
}
}
} else {
for (size_t i = 0; i < renderableTileEntities.size(); i++) {
renderableTileEntities[i]->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageKeep);
levelRenderer->addRenderableTileEntity_Locked(
key, renderableTileEntities[i]);
}
}
} else if (it != globalRenderableTileEntities->end()) {
for (AUTO_VAR(it2, it->second.tiles.begin());
it2 != it->second.tiles.end();
it2++) {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
levelRenderer->queueRenderableTileEntityForRemoval_Locked(key,
(*it2).get());
}
}
}
// TODO - 4J see how input entity vector is set up and decide what way is best
// to pass this to the function
Chunk::Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities,
@ -72,6 +134,7 @@ void Chunk::setPos(int x, int y, int z) {
clipChunk->globalIdx =
LevelRenderer::getGlobalIndexForChunk(x, y, z, level);
levelRenderer->setGlobalChunkConnectivity(clipChunk->globalIdx, ~0ULL);
#if 1
// 4J - we're not using offsetted renderlists anymore, so just set the full
@ -252,94 +315,97 @@ void Chunk::rebuild() {
// into this category. By far the largest category of these are tiles in
// solid regions of rock.
bool empty = true;
for (int yy = y0; yy < y1; yy++) {
for (int zz = 0; zz < 16; zz++) {
for (int xx = 0; xx < 16; xx++) {
// 4J Stu - tile data is ordered in 128 blocks of full width,
// lower 128 then upper 128
int indexY = yy;
int offset = 0;
if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
unsigned char tileId =
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
(indexY + 0))];
if (tileId > 0) empty = false;
// Don't bother trying to work out neighbours for this tile if
// we are at the edge of the chunk - apart from the very bottom
// of the world where we shouldn't ever be able to see
if (yy == (Level::maxBuildHeight - 1)) continue;
if ((xx == 0) || (xx == 15)) continue;
if ((zz == 0) || (zz == 15)) continue;
// Establish whether this tile and its neighbours are all made
// of rock, dirt, unbreakable tiles, or have already been
// determined to meet this criteria themselves and have a tile
// of 255 set.
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx - 1) << 11) | ((zz + 0) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx + 1) << 11) | ((zz + 0) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz - 1) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz + 1) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
// Treat the bottom of the world differently - we shouldn't ever
// be able to look up at this, so consider tiles as invisible if
// they are surrounded on sides other than the bottom
if (yy > 0) {
int indexYMinusOne = yy - 1;
int yMinusOneOffset = 0;
if (indexYMinusOne >=
Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexYMinusOne -=
Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
yMinusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
{
FRAME_PROFILE_SCOPE(ChunkPrepass);
for (int yy = y0; yy < y1; yy++) {
for (int zz = 0; zz < 16; zz++) {
for (int xx = 0; xx < 16; xx++) {
// 4J Stu - tile data is ordered in 128 blocks of full width,
// lower 128 then upper 128
int indexY = yy;
int offset = 0;
if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
tileId = tileIds[yMinusOneOffset + (((xx + 0) << 11) |
((zz + 0) << 7) |
indexYMinusOne)];
if (!((tileId == Tile::stone_Id) ||
(tileId == Tile::dirt_Id) ||
unsigned char tileId =
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
(indexY + 0))];
if (tileId > 0) empty = false;
// Don't bother trying to work out neighbours for this tile if
// we are at the edge of the chunk - apart from the very bottom
// of the world where we shouldn't ever be able to see
if (yy == (Level::maxBuildHeight - 1)) continue;
if ((xx == 0) || (xx == 15)) continue;
if ((zz == 0) || (zz == 15)) continue;
// Establish whether this tile and its neighbours are all made
// of rock, dirt, unbreakable tiles, or have already been
// determined to meet this criteria themselves and have a tile
// of 255 set.
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx - 1) << 11) | ((zz + 0) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx + 1) << 11) | ((zz + 0) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz - 1) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
tileId = tileIds[offset + (((xx + 0) << 11) | ((zz + 1) << 7) |
(indexY + 0))];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
// Treat the bottom of the world differently - we shouldn't ever
// be able to look up at this, so consider tiles as invisible if
// they are surrounded on sides other than the bottom
if (yy > 0) {
int indexYMinusOne = yy - 1;
int yMinusOneOffset = 0;
if (indexYMinusOne >=
Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexYMinusOne -=
Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
yMinusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
tileId = tileIds[yMinusOneOffset + (((xx + 0) << 11) |
((zz + 0) << 7) |
indexYMinusOne)];
if (!((tileId == Tile::stone_Id) ||
(tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
}
int indexYPlusOne = yy + 1;
int yPlusOneOffset = 0;
if (indexYPlusOne >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexYPlusOne -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
yPlusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
tileId =
tileIds[yPlusOneOffset + (((xx + 0) << 11) |
((zz + 0) << 7) | indexYPlusOne)];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
}
int indexYPlusOne = yy + 1;
int yPlusOneOffset = 0;
if (indexYPlusOne >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexYPlusOne -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
yPlusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
tileId =
tileIds[yPlusOneOffset + (((xx + 0) << 11) |
((zz + 0) << 7) | indexYPlusOne)];
if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
// This tile is surrounded. Flag it as not requiring to be
// rendered by setting its id to 255.
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
(indexY + 0))] = 0xff;
// This tile is surrounded. Flag it as not requiring to be
// rendered by setting its id to 255.
tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
(indexY + 0))] = 0xff;
}
}
}
}
@ -354,6 +420,12 @@ void Chunk::rebuild() {
RenderManager.CBuffClear(lists + currentLayer);
}
int globalIdx = levelRenderer->getGlobalIndexForChunk(this->x, this->y,
this->z, level);
levelRenderer->setGlobalChunkConnectivity(globalIdx, ~0ULL);
levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level,
LevelRenderer::CHUNK_FLAG_COMPILED);
delete region;
delete tileRenderer;
return;
@ -410,20 +482,8 @@ void Chunk::rebuild() {
MemSect(31);
glNewList(lists + currentLayer, GL_COMPILE);
MemSect(0);
glPushMatrix();
glDepthMask(true); // 4J added
t->useCompactVertices(true); // 4J added
translateToPos();
float ss = 1.000001f;
// 4J - have removed this scale as I don't think we
// should need it, and have now optimised the vertex
// shader so it doesn't do anything other than
// translate with this matrix anyway
#if 0
glTranslatef(-zs / 2.0f, -ys / 2.0f, -zs / 2.0f);
glScalef(ss, ss, ss);
glTranslatef(zs / 2.0f, ys / 2.0f, zs / 2.0f);
#endif
t->begin();
t->offset((float)(-this->x), (float)(-this->y),
(float)(-this->z));
@ -471,7 +531,6 @@ void Chunk::rebuild() {
#endif
t->end();
bounds.addBounds(t->bounds); // 4J MGH - added
glPopMatrix();
glEndList();
t->useCompactVertices(false); // 4J added
t->offset(0, 0, 0);
@ -504,6 +563,11 @@ void Chunk::rebuild() {
bb = {bounds.boundingBox[0], bounds.boundingBox[1], bounds.boundingBox[2],
bounds.boundingBox[3], bounds.boundingBox[4], bounds.boundingBox[5]};
uint64_t conn = computeConnectivity(tileIds); // pass tileIds
int globalIdx =
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
levelRenderer->setGlobalChunkConnectivity(globalIdx, conn);
delete tileRenderer;
delete region;
@ -516,57 +580,8 @@ void Chunk::rebuild() {
// from the dimension and chunk position (using same index as is used for
// global flags)
#if 1
int key =
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
EnterCriticalSection(globalRenderableTileEntities_cs);
if (renderableTileEntities.size()) {
AUTO_VAR(it, globalRenderableTileEntities->find(key));
if (it != globalRenderableTileEntities->end()) {
// We've got some renderable tile entities that we want associated
// with this chunk, and an existing list of things that used to be.
// We need to flag any that we don't need any more to be removed,
// keep those that we do, and add any new ones
// First pass - flag everything already existing to be removed
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
it2++) {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
}
// Now go through the current list. If these are already in the
// list, then unflag the remove flag. If they aren't, then add
for (int i = 0; i < renderableTileEntities.size(); i++) {
AUTO_VAR(it2, find(it->second.begin(), it->second.end(),
renderableTileEntities[i]));
if (it2 == it->second.end()) {
(*globalRenderableTileEntities)[key].push_back(
renderableTileEntities[i]);
} else {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageKeep);
}
}
} else {
// Easy case - nothing already existing for this chunk. Add them all
// in.
for (int i = 0; i < renderableTileEntities.size(); i++) {
(*globalRenderableTileEntities)[key].push_back(
renderableTileEntities[i]);
}
}
} else {
// Another easy case - we don't want any renderable tile entities
// associated with this chunk. Flag all to be removed.
AUTO_VAR(it, globalRenderableTileEntities->find(key));
if (it != globalRenderableTileEntities->end()) {
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
it2++) {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
}
}
}
reconcileRenderableTileEntities(renderableTileEntities);
LeaveCriticalSection(globalRenderableTileEntities_cs);
PIXEndNamedEvent();
#else
@ -734,19 +749,8 @@ void Chunk::rebuild_SPU() {
{
glNewList(lists + currentLayer, GL_COMPILE);
MemSect(0);
glPushMatrix();
glDepthMask(true); // 4J added
t->useCompactVertices(true); // 4J added
translateToPos();
float ss = 1.000001f;
// 4J - have removed this scale as I don't think we should need it,
// and have now optimised the vertex shader so it doesn't do
// anything other than translate with this matrix anyway
#if 0
glTranslatef(-zs / 2.0f, -ys / 2.0f, -zs / 2.0f);
glScalef(ss, ss, ss);
glTranslatef(zs / 2.0f, ys / 2.0f, zs / 2.0f);
#endif
t->begin();
t->offset((float)(-this->x), (float)(-this->y), (float)(-this->z));
}
@ -776,7 +780,7 @@ void Chunk::rebuild_SPU() {
if (currentLayer == 0 &&
Tile::tiles[tileId]->isEntityTile()) {
std::shared_ptr<TileEntity> et =
region.getTileEntity(x, y, z);
region->getTileEntity(x, y, z);
if (TileEntityRenderDispatcher::instance
->hasRenderer(et)) {
renderableTileEntities.push_back(et);
@ -794,7 +798,7 @@ void Chunk::rebuild_SPU() {
} else if (renderLayer == currentLayer) {
// if(currentLayer == 0)
// numRenderedLayer0++;
rendered |= tileRenderer.tesselateInWorld(
rendered |= tileRenderer->tesselateInWorld(
tile, x, y, z);
}
}
@ -806,7 +810,6 @@ void Chunk::rebuild_SPU() {
{
t->end();
bounds.addBounds(t->bounds);
glPopMatrix();
glEndList();
t->useCompactVertices(false); // 4J added
t->offset(0, 0, 0);
@ -840,57 +843,8 @@ void Chunk::rebuild_SPU() {
// from the dimension and chunk position (using same index as is used for
// global flags)
#if 1
int key =
levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
EnterCriticalSection(globalRenderableTileEntities_cs);
if (renderableTileEntities.size()) {
AUTO_VAR(it, globalRenderableTileEntities->find(key));
if (it != globalRenderableTileEntities->end()) {
// We've got some renderable tile entities that we want associated
// with this chunk, and an existing list of things that used to be.
// We need to flag any that we don't need any more to be removed,
// keep those that we do, and add any new ones
// First pass - flag everything already existing to be removed
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
it2++) {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
}
// Now go through the current list. If these are already in the
// list, then unflag the remove flag. If they aren't, then add
for (int i = 0; i < renderableTileEntities.size(); i++) {
AUTO_VAR(it2, find(it->second.begin(), it->second.end(),
renderableTileEntities[i]));
if (it2 == it->second.end()) {
(*globalRenderableTileEntities)[key].push_back(
renderableTileEntities[i]);
} else {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageKeep);
}
}
} else {
// Easy case - nothing already existing for this chunk. Add them all
// in.
for (int i = 0; i < renderableTileEntities.size(); i++) {
(*globalRenderableTileEntities)[key].push_back(
renderableTileEntities[i]);
}
}
} else {
// Another easy case - we don't want any renderable tile entities
// associated with this chunk. Flag all to be removed.
AUTO_VAR(it, globalRenderableTileEntities->find(key));
if (it != globalRenderableTileEntities->end()) {
for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
it2++) {
(*it2)->setRenderRemoveStage(
TileEntity::e_RenderRemoveStageFlaggedAtChunk);
}
}
}
reconcileRenderableTileEntities(renderableTileEntities);
LeaveCriticalSection(globalRenderableTileEntities_cs);
#else
// Find the removed ones:
@ -979,17 +933,157 @@ float Chunk::squishedDistanceToSqr(std::shared_ptr<Entity> player) {
return xd * xd + yd * yd + zd * zd;
}
uint64_t Chunk::computeConnectivity(const uint8_t* tileIds) {
const int W = 16;
const int H = 16;
const int VOLUME = W * H * W;
auto idx = [&](int x, int y, int z) -> int {
return y * W * W + z * W + x;
};
auto isOpen = [&](int lx, int ly, int lz) -> bool {
int worldY = this->y + ly;
int offset = 0;
int indexY = worldY;
if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
uint8_t tileId = tileIds[offset + ((lx << 11) | (lz << 7) | indexY)];
if (tileId == 0) return true; // air
if (tileId == 0xFF) return false; // hidden tile (yeah)
Tile* t = Tile::tiles[tileId];
return (t == nullptr) || !t->isSolidRender();
};
uint8_t visited[6][512];
memset(visited, 0, sizeof(visited));
static const int FX[6] = {1, -1, 0, 0, 0, 0};
static const int FY[6] = {0, 0, 1, -1, 0, 0};
static const int FZ[6] = {0, 0, 0, 0, 1, -1};
struct Cell {
int8_t x, y, z;
};
static thread_local std::vector<Cell> queue;
uint64_t result = 0;
for (int entryFace = 0; entryFace < 6; entryFace++) {
uint8_t* vis = visited[entryFace];
queue.clear();
int x0s, x1s, y0s, y1s, z0s, z1s;
switch (entryFace) {
case 0:
x0s = W - 1;
x1s = W - 1;
y0s = 0;
y1s = H - 1;
z0s = 0;
z1s = W - 1;
break; // +X
case 1:
x0s = 0;
x1s = 0;
y0s = 0;
y1s = H - 1;
z0s = 0;
z1s = W - 1;
break; // -X
case 2:
x0s = 0;
x1s = W - 1;
y0s = H - 1;
y1s = H - 1;
z0s = 0;
z1s = W - 1;
break; // +Y
case 3:
x0s = 0;
x1s = W - 1;
y0s = 0;
y1s = 0;
z0s = 0;
z1s = W - 1;
break; // -Y
case 4:
x0s = 0;
x1s = W - 1;
y0s = 0;
y1s = H - 1;
z0s = W - 1;
z1s = W - 1;
break; // +Z
case 5:
x0s = 0;
x1s = W - 1;
y0s = 0;
y1s = H - 1;
z0s = 0;
z1s = 0;
break; // -Z
default:
continue;
}
for (int sy = y0s; sy <= y1s; sy++)
for (int sz = z0s; sz <= z1s; sz++)
for (int sx = x0s; sx <= x1s; sx++) {
if (!isOpen(sx, sy, sz)) continue;
int i = idx(sx, sy, sz);
if (vis[i >> 3] & (1 << (i & 7))) continue;
vis[i >> 3] |= (1 << (i & 7));
queue.push_back({(int8_t)sx, (int8_t)sy, (int8_t)sz});
}
for (int qi = 0; qi < (int)queue.size(); qi++) {
Cell cur = queue[qi];
for (int nb = 0; nb < 6; nb++) {
int nx = cur.x + FX[nb];
int ny = cur.y + FY[nb];
int nz = cur.z + FZ[nb];
// entry exit conn
if (nx < 0 || nx >= W || ny < 0 || ny >= H || nz < 0 ||
nz >= W) {
// nb IS the exit face because FX,FY,FZ are aligned
result |= ((uint64_t)1 << (entryFace * 6 + nb));
continue;
}
if (!isOpen(nx, ny, nz)) continue;
int i = idx(nx, ny, nz);
if (vis[i >> 3] & (1 << (i & 7))) continue;
vis[i >> 3] |= (1 << (i & 7));
queue.push_back({(int8_t)nx, (int8_t)ny, (int8_t)nz});
}
}
}
return result;
}
void Chunk::reset() {
if (assigned) {
int oldKey = -1;
bool retireRenderableTileEntities = false;
EnterCriticalSection(&levelRenderer->m_csDirtyChunks);
oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
unsigned char refCount =
levelRenderer->decGlobalChunkRefCount(x, y, z, level);
assigned = false;
// printf("\t\t [dec] refcount %d at %d, %d,
//%d\n",refCount,x,y,z);
if (refCount == 0) {
int lists =
levelRenderer->getGlobalIndexForChunk(x, y, z, level) * 2;
if (refCount == 0 && oldKey != -1) {
retireRenderableTileEntities = true;
int lists = oldKey * 2;
if (lists >= 0) {
lists += levelRenderer->chunkLists;
for (int i = 0; i < 2; i++) {
@ -1001,6 +1095,10 @@ void Chunk::reset() {
}
}
LeaveCriticalSection(&levelRenderer->m_csDirtyChunks);
if (retireRenderableTileEntities) {
levelRenderer->retireRenderableTileEntitiesForChunkKey(oldKey);
}
}
clipChunk->visible = false;
@ -1023,7 +1121,11 @@ int Chunk::getList(int layer) {
return -1;
}
void Chunk::cull(Culler* culler) { clipChunk->visible = culler->isVisible(&bb); }
void Chunk::cull(Culler* culler) {
if (clipChunk->visible) {
clipChunk->visible = culler->isVisible(&bb);
}
}
void Chunk::renderBB() {
// glCallList(lists + 2); // 4J - removed - TODO put back in

View file

@ -48,7 +48,7 @@ public:
int xm, ym, zm;
AABB bb;
ClipChunk* clipChunk;
uint64_t computeConnectivity(const uint8_t* tileIds);
int id;
// public:
// std::vector<std::shared_ptr<TileEntity> > renderableTileEntities;
@ -69,6 +69,8 @@ public:
private:
void translateToPos();
void reconcileRenderableTileEntities(
const std::vector<std::shared_ptr<TileEntity> >& renderableTileEntities);
public:
void makeCopyForRebuild(Chunk* source);

View file

@ -361,10 +361,10 @@ void ItemRenderer::renderGuiItem(Font* font, Textures* textures,
// 4J - original code left here for reference
// 4jcraft: original code reused for proper lighting
#if 1
glTranslatef((float)(x), (float)(y), 0.0f);
glScalef(fScaleX, fScaleY, 1.0f);
glTranslatef(-2.0f,3.0f, -3.0f + blitOffset);
glScalef(10.0f, 10.0f, 10.0f);
glTranslatef((float)(x), (float)(y), 0.0f);
glScalef(fScaleX, fScaleY, 1.0f);
glTranslatef(-2.0f, 3.0f, -3.0f + blitOffset);
glScalef(10.0f, 10.0f, 10.0f);
glTranslatef(1.0f, 0.5f, 8.0f);
glScalef(1.0f, 1.0f, -1.0f);
glRotatef(180.0f + 30.0f, 1.0f, 0.0f, 0.0f);
@ -385,10 +385,11 @@ void ItemRenderer::renderGuiItem(Font* font, Textures* textures,
glRotatef(45.0f, 0.0f, 1.0f,
0.0f); // Rotate round y axis (centre at origin)
#endif
// 4J-PB - pass the alpha value in - the grass block
// render has the top surface coloured differently to
// the rest of the block
glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
// 4J-PB - pass the alpha value in - the grass block
// render has the top surface coloured differently to
// the rest of the block
glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
tileRenderer->renderTile(tile, itemAuxValue, 1, fAlpha, useCompiled);
glPopMatrix();

View file

@ -11,6 +11,7 @@
#include "../../../Minecraft.World/Headers/net.minecraft.h"
#include "../../../Minecraft.World/Headers/net.minecraft.world.h"
#include "../Tesselator.h"
#include "../../Utils/FrameProfiler.h"
#include "EntityTileRenderer.h"
#include "../../GameState/Options.h"
@ -267,7 +268,12 @@ bool TileRenderer::tesselateInWorld(
{
Tesselator* t = Tesselator::getInstance();
int shape = tt->getRenderShape();
tt->updateShape(level, x, y, z, forceData, forceEntity);
if (shape == Tile::SHAPE_BLOCK) {
FRAME_PROFILE_SCOPE(ChunkBlockShape);
tt->updateShape(level, x, y, z, forceData, forceEntity);
} else {
tt->updateShape(level, x, y, z, forceData, forceEntity);
}
// AP - now that the culling is done earlier we don't need to call setShape
// until later on (only for SHAPE_BLOCK)
if (shape != Tile::SHAPE_BLOCK) {
@ -278,6 +284,11 @@ bool TileRenderer::tesselateInWorld(
bool retVal = false;
switch (shape) {
case Tile::SHAPE_BLOCK: {
{
FRAME_PROFILE_SCOPE(ChunkBlockShape);
setShape(tt);
}
// 4J - added these faceFlags so we can detect whether this block is
// going to have no visible faces and early out the original code
// checked noCulling and shouldRenderFace directly where faceFlags
@ -290,6 +301,7 @@ bool TileRenderer::tesselateInWorld(
if (noCulling) {
faceFlags = 0x3f;
} else {
FRAME_PROFILE_SCOPE(ChunkBlockFaceCull);
// these block types can take advantage of a faster version of
// shouldRenderFace there are others but this is an easy check
// which covers the majority Note: This now covers rock, grass,
@ -319,9 +331,6 @@ bool TileRenderer::tesselateInWorld(
break;
}
// now we need to set the shape
setShape(tt);
retVal = tesselateBlockInWorld(tt, x, y, z, faceFlags);
} break;
case Tile::SHAPE_TREE:
@ -4828,9 +4837,11 @@ bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z) {
if (Tile::lightEmission[tt->id] ==
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
{
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
tt, x, y, z, r, g, b, 0, smoothShapeLighting);
} else {
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
}
}
@ -4856,9 +4867,11 @@ bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z,
if (Tile::lightEmission[tt->id] ==
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
{
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
tt, x, y, z, r, g, b, faceFlags, smoothShapeLighting);
} else {
FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
}
}
@ -7049,6 +7062,7 @@ bool TileRenderer::tesselateDoorInWorld(Tile* tt, int x, int y, int z) {
void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
Icon* tex) {
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@ -7167,6 +7181,7 @@ void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
Icon* tex) {
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@ -7286,6 +7301,7 @@ void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
Icon* tex) {
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@ -7410,6 +7426,7 @@ void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
Icon* tex) {
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@ -7534,6 +7551,7 @@ void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
Icon* tex) {
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@ -7658,6 +7676,7 @@ void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
void TileRenderer::renderEast(Tile* tt, double x, double y, double z,
Icon* tex) {
FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;

View file

@ -1,9 +1,11 @@
#include "../Platform/stdafx.h"
#include "../../Minecraft.World/IO/Streams/FloatBuffer.h"
#include "Frustum.h"
#include "Camera.h"
Frustum* Frustum::frustum = new Frustum();
// those are now unused but i still gotta do testing.
Frustum::Frustum() {
_proj = MemoryTracker::createFloatBuffer(16);
_modl = MemoryTracker::createFloatBuffer(16);
@ -43,63 +45,38 @@ void Frustum::normalizePlane(float** frustum, int side) {
}
void Frustum::calculateFrustum() {
_proj->clear();
_modl->clear();
_clip->clear();
// 4jcraft: GL 3.3 core removed GL_MODELVIEW_MATRIX / GL_PROJECTION_MATRIX
// queries.
// Camera::prepare() already captures both matrices every frame :)
// i spent an ungodly amount of time on this simple fix.
memcpy(proj.data, RenderManager.MatrixGet(GL_PROJECTION_MATRIX),
16 * sizeof(float));
memcpy(modl.data, RenderManager.MatrixGet(GL_MODELVIEW_MATRIX),
16 * sizeof(float));
// glGetFloatv() is used to extract information about our OpenGL world.
// Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
// It then stores the matrix into an array of [16].
glGetFloat(GL_PROJECTION_MATRIX, _proj);
float* p = proj.data;
float* m = modl.data;
float* c = clip.data;
// By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
// This also stores it in an array of [16].
glGetFloat(GL_MODELVIEW_MATRIX, _modl);
c[0] = m[0] * p[0] + m[1] * p[4] + m[2] * p[8] + m[3] * p[12];
c[1] = m[0] * p[1] + m[1] * p[5] + m[2] * p[9] + m[3] * p[13];
c[2] = m[0] * p[2] + m[1] * p[6] + m[2] * p[10] + m[3] * p[14];
c[3] = m[0] * p[3] + m[1] * p[7] + m[2] * p[11] + m[3] * p[15];
_proj->flip()->limit(16);
_proj->get(&proj);
_modl->flip()->limit(16);
_modl->get(&modl);
c[4] = m[4] * p[0] + m[5] * p[4] + m[6] * p[8] + m[7] * p[12];
c[5] = m[4] * p[1] + m[5] * p[5] + m[6] * p[9] + m[7] * p[13];
c[6] = m[4] * p[2] + m[5] * p[6] + m[6] * p[10] + m[7] * p[14];
c[7] = m[4] * p[3] + m[5] * p[7] + m[6] * p[11] + m[7] * p[15];
// Now that we have our modelview and projection matrix, if we combine these
// 2 matrices, it will give us our clipping planes. To combine 2 matrices,
// we multiply them.
c[8] = m[8] * p[0] + m[9] * p[4] + m[10] * p[8] + m[11] * p[12];
c[9] = m[8] * p[1] + m[9] * p[5] + m[10] * p[9] + m[11] * p[13];
c[10] = m[8] * p[2] + m[9] * p[6] + m[10] * p[10] + m[11] * p[14];
c[11] = m[8] * p[3] + m[9] * p[7] + m[10] * p[11] + m[11] * p[15];
clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] +
modl[3] * proj[12];
clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] +
modl[3] * proj[13];
clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] +
modl[3] * proj[14];
clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] +
modl[3] * proj[15];
clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] +
modl[7] * proj[12];
clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] +
modl[7] * proj[13];
clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] +
modl[7] * proj[14];
clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] +
modl[7] * proj[15];
clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] +
modl[11] * proj[12];
clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] +
modl[11] * proj[13];
clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] +
modl[11] * proj[14];
clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] +
modl[11] * proj[15];
clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] +
modl[15] * proj[12];
clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] +
modl[15] * proj[13];
clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] +
modl[15] * proj[14];
clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] +
modl[15] * proj[15];
c[12] = m[12] * p[0] + m[13] * p[4] + m[14] * p[8] + m[15] * p[12];
c[13] = m[12] * p[1] + m[13] * p[5] + m[14] * p[9] + m[15] * p[13];
c[14] = m[12] * p[2] + m[13] * p[6] + m[14] * p[10] + m[15] * p[14];
c[15] = m[12] * p[3] + m[13] * p[7] + m[14] * p[11] + m[15] * p[15];
// Now we actually want to get the sides of the frustum. To do this we take
// the clipping planes we received above and extract the sides from them.

View file

@ -1,11 +1,13 @@
#include "../Platform/stdafx.h"
#include "FrustumData.h"
float** m_Frustum;
// float** m_Frustum;
FrustumData::FrustumData() {
m_Frustum = new float*[16];
for (int i = 0; i < 16; i++) m_Frustum[i] = new float[16];
this->m_Frustum = new float*[6];
for (int i = 0; i < 6; i++) {
this->m_Frustum[i] = new float[4];
}
proj = floatArray(16);
modl = floatArray(16);
clip = floatArray(16);
@ -15,7 +17,7 @@ FrustumData::~FrustumData() {
delete[] proj.data;
delete[] modl.data;
delete[] clip.data;
for (int i = 0; i < 16; i++) delete[] m_Frustum[i];
for (int i = 0; i < 6; i++) delete[] m_Frustum[i];
delete[] m_Frustum;
}
@ -128,4 +130,4 @@ bool FrustumData::cubeInFrustum(double x1, double y1, double z1, double x2,
bool FrustumData::isVisible(AABB* aabb) {
return cubeInFrustum(aabb->x0, aabb->y0, aabb->z0, aabb->x1, aabb->y1,
aabb->z1);
}
}

View file

@ -50,6 +50,7 @@
#include "../Textures/Packs/TexturePackRepository.h"
#include "../Textures/Packs/TexturePack.h"
#include "../Textures/TextureAtlas.h"
#include "../Utils/FrameProfiler.h"
bool GameRenderer::anaglyph3d = false;
int GameRenderer::anaglyphPass = 0;
@ -72,6 +73,9 @@ ResourceLocation GameRenderer::RAIN_LOCATION =
ResourceLocation GameRenderer::SNOW_LOCATION =
ResourceLocation(TN_ENVIRONMENT_SNOW);
// dirty light tracking
static bool s_lightTexDirty[XUSER_MAX_COUNT] = {true, true, true, true};
GameRenderer::GameRenderer(Minecraft* mc) {
// 4J - added this block of initialisers
renderDistance = 0;
@ -773,6 +777,7 @@ void GameRenderer::renderItemInHand(float a, int eye) {
// 4J - change brought forward from 1.8.2
void GameRenderer::turnOffLightLayer(double alpha) { // 4J - TODO
FRAME_PROFILE_SCOPE(Lightmap);
#ifdef __linux__
if (SharedConstants::TEXTURE_LIGHTING) {
LinuxLogStubLightmapProbe();
@ -804,6 +809,7 @@ void GameRenderer::turnOffLightLayer(double alpha) { // 4J - TODO
void GameRenderer::turnOnLightLayer(
double alpha,
bool scaleLight) { // 4jcraft: added scaleLight for entity lighting
FRAME_PROFILE_SCOPE(Lightmap);
#ifdef __linux__
if (!SharedConstants::TEXTURE_LIGHTING) return;
@ -871,9 +877,14 @@ void GameRenderer::tickLightTexture() {
blr += (blrt - blr) * 1;
blg += (blgt - blg) * 1;
_updateLightTexture = true;
// Mark all players dirty so updateLightTexture() knows when it actually
// needs to tick, preventz unessesary player recompute
for (int j = 0; j < XUSER_MAX_COUNT; j++) s_lightTexDirty[j] = true;
}
void GameRenderer::updateLightTexture(float a) {
FRAME_PROFILE_SCOPE(Lightmap);
// 4J-JEV: Now doing light textures on PER PLAYER basis.
// 4J - we *had* added separate light textures for all dimensions, and this
// loop to update them all here
@ -883,8 +894,10 @@ void GameRenderer::updateLightTexture(float a) {
Minecraft::GetInstance()->localplayers[j];
if (player == NULL) continue;
Level* level = player->level; // 4J - was mc->level when it was just to
// update the one light texture
if (!s_lightTexDirty[j]) continue;
s_lightTexDirty[j] = false;
Level* level = player->level;
float skyDarken1 = level->getSkyDarken((float)1);
for (int i = 0; i < 256; i++) {
@ -964,10 +977,10 @@ void GameRenderer::updateLightTexture(float a) {
_b = _b * 0.96f + 0.03f;
if (_r > 1) _r = 1;
if (_g > 1) _g = 1;
if (_b > 1) _b = 1;
if (_r < 0) _r = 0;
if (_g > 1) _g = 1;
if (_g < 0) _g = 0;
if (_b > 1) _b = 1;
if (_b < 0) _b = 0;
int alpha = 255;
@ -1016,6 +1029,8 @@ int GameRenderer::getLightTexture(int iPad, Level* level) {
}
void GameRenderer::render(float a, bool bFirst) {
FRAME_PROFILE_FRAME_SCOPE();
if (_updateLightTexture && bFirst) updateLightTexture(a);
if (Display::isActive()) {
lastActiveTime = System::currentTimeMillis();
@ -1074,6 +1089,7 @@ void GameRenderer::render(float a, bool bFirst) {
lastNsTime = System::nanoTime();
if (!mc->options->hideGui || mc->screen != NULL) {
FRAME_PROFILE_SCOPE(UIHud);
mc->gui->render(a, mc->screen != NULL, xMouse, yMouse);
}
} else {
@ -1088,6 +1104,7 @@ void GameRenderer::render(float a, bool bFirst) {
}
if (mc->screen != NULL) {
FRAME_PROFILE_SCOPE(UIHud);
glClear(GL_DEPTH_BUFFER_BIT);
mc->screen->render(xMouse, yMouse, a);
if (mc->screen != NULL && mc->screen->particles != NULL)
@ -1180,24 +1197,19 @@ int GameRenderer::runUpdate(void* lpParam) {
// We've got stacks for things that can only safely be deleted whilst
// this thread isn't updating things - delete those things now
EnterCriticalSection(&m_csDeleteStack);
for (unsigned int i = 0; i < m_deleteStackByte.size(); i++) {
for (unsigned int i = 0; i < m_deleteStackByte.size(); i++)
delete m_deleteStackByte[i];
}
m_deleteStackByte.clear();
for (unsigned int i = 0; i < m_deleteStackSparseLightStorage.size();
i++) {
i++)
delete m_deleteStackSparseLightStorage[i];
}
m_deleteStackSparseLightStorage.clear();
for (unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size();
i++) {
i++)
delete m_deleteStackCompressedTileStorage[i];
}
m_deleteStackCompressedTileStorage.clear();
for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size();
i++) {
for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++)
delete m_deleteStackSparseDataStorage[i];
}
m_deleteStackSparseDataStorage.clear();
LeaveCriticalSection(&m_csDeleteStack);
@ -1240,6 +1252,8 @@ void GameRenderer::DisableUpdateThread() {
}
void GameRenderer::renderLevel(float a, int64_t until) {
FRAME_PROFILE_SCOPE(World);
// if (updateLightTexture) updateLightTexture(); // 4J - TODO -
// Java 1.0.1 has this line enabled, should check why - don't want to put it
// in now in case it breaks split-screen
@ -1292,9 +1306,12 @@ void GameRenderer::renderLevel(float a, int64_t until) {
Frustum::getFrustum();
if (mc->options->viewDistance < 2) {
setupFog(-1, a);
levelRenderer->renderSky(a);
if (mc->skins->getSelected()->getId() == 1026)
levelRenderer->renderHaloRing(a);
{
FRAME_PROFILE_SCOPE(WeatherSky);
levelRenderer->renderSky(a);
if (mc->skins->getSelected()->getId() == 1026)
levelRenderer->renderHaloRing(a);
}
}
// 4jcraft: needs to be enabled for proper transparent texturing on low
// render dists this was done in renderSky() for the far and normal
@ -1316,7 +1333,10 @@ void GameRenderer::renderLevel(float a, int64_t until) {
MemSect(0);
frustum->prepare(xOff, yOff, zOff);
mc->levelRenderer->cull(frustum, a);
{
FRAME_PROFILE_SCOPE(ChunkCull);
mc->levelRenderer->cull(frustum, a);
}
PIXEndNamedEvent();
#ifndef MULTITHREAD_ENABLE
@ -1343,6 +1363,7 @@ void GameRenderer::renderLevel(float a, int64_t until) {
#endif
if (cameraEntity->y < Level::genDepth) {
FRAME_PROFILE_SCOPE(WeatherSky);
prepareAndRenderClouds(levelRenderer, a);
}
Frustum::getFrustum(); // 4J added - re-calculate frustum as rendering
@ -1381,7 +1402,10 @@ void GameRenderer::renderLevel(float a, int64_t until) {
cameraPos.x = cameraPosTemp.x;
cameraPos.y = cameraPosTemp.y;
cameraPos.z = cameraPosTemp.z;
levelRenderer->renderEntities(&cameraPos, frustum, a);
{
FRAME_PROFILE_SCOPE(Entity);
levelRenderer->renderEntities(&cameraPos, frustum, a);
}
#ifdef __PSVITA__
// AP - make sure we're using the Alpha cut out effect for particles
glEnable(GL_ALPHA_TEST);
@ -1389,12 +1413,18 @@ void GameRenderer::renderLevel(float a, int64_t until) {
PIXEndNamedEvent();
PIXBeginNamedEvent(0, "Particle render");
turnOnLightLayer(a); // 4J - brought forward from 1.8.2
particleEngine->renderLit(cameraEntity, a,
ParticleEngine::OPAQUE_LIST);
{
FRAME_PROFILE_SCOPE(Particle);
particleEngine->renderLit(cameraEntity, a,
ParticleEngine::OPAQUE_LIST);
}
Lighting::turnOff();
setupFog(0, a);
particleEngine->render(cameraEntity, a,
ParticleEngine::OPAQUE_LIST);
{
FRAME_PROFILE_SCOPE(Particle);
particleEngine->render(cameraEntity, a,
ParticleEngine::OPAQUE_LIST);
}
PIXEndNamedEvent();
turnOffLightLayer(a); // 4J - brought forward from 1.8.2
@ -1463,12 +1493,18 @@ void GameRenderer::renderLevel(float a, int64_t until) {
PIXBeginNamedEvent(0, "Particle render (translucent)");
Lighting::turnOn();
turnOnLightLayer(a); // 4J - brought forward from 1.8.2
particleEngine->renderLit(cameraEntity, a,
ParticleEngine::TRANSLUCENT_LIST);
{
FRAME_PROFILE_SCOPE(Particle);
particleEngine->renderLit(cameraEntity, a,
ParticleEngine::TRANSLUCENT_LIST);
}
Lighting::turnOff();
setupFog(0, a);
particleEngine->render(cameraEntity, a,
ParticleEngine::TRANSLUCENT_LIST);
{
FRAME_PROFILE_SCOPE(Particle);
particleEngine->render(cameraEntity, a,
ParticleEngine::TRANSLUCENT_LIST);
}
PIXEndNamedEvent();
turnOffLightLayer(a); // 4J - brought forward from 1.8.2
////////////////////////// End of 4J added section
@ -1499,12 +1535,16 @@ void GameRenderer::renderLevel(float a, int64_t until) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
levelRenderer->renderDestroyAnimation(
Tesselator::getInstance(),
std::dynamic_pointer_cast<Player>(cameraEntity), a);
{
FRAME_PROFILE_SCOPE(WeatherSky);
levelRenderer->renderDestroyAnimation(
Tesselator::getInstance(),
std::dynamic_pointer_cast<Player>(cameraEntity), a);
}
glDisable(GL_BLEND);
if (cameraEntity->y >= Level::genDepth) {
FRAME_PROFILE_SCOPE(WeatherSky);
prepareAndRenderClouds(levelRenderer, a);
}
@ -1513,7 +1553,10 @@ void GameRenderer::renderLevel(float a, int64_t until) {
setupFog(0, a);
glEnable(GL_FOG);
PIXBeginNamedEvent(0, "Rendering snow and rain");
renderSnowAndRain(a);
{
FRAME_PROFILE_SCOPE(WeatherSky);
renderSnowAndRain(a);
}
PIXEndNamedEvent();
glDisable(GL_FOG);
@ -1700,135 +1743,144 @@ void GameRenderer::renderSnowAndRain(float a) {
glColor4f(1, 1, 1, 1);
for (int x = x0 - r; x <= x0 + r; x++)
// two snow/rain rendering
mc->textures->bindTexture(&RAIN_LOCATION);
t->begin();
for (int x = x0 - r; x <= x0 + r; x++) {
for (int z = z0 - r; z <= z0 + r; z++) {
int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16);
float xa = rainXa[rainSlot] * 0.5f;
float za = rainZa[rainSlot] * 0.5f;
// 4J - changes here brought forward from 1.8.2
Biome* b = level->getBiome(x, z);
if (!b->hasRain() && !b->hasSnow()) continue;
int floor = level->getTopRainBlock(x, z);
int yy0 = y0 - r;
int yy1 = y0 + r;
if (yy0 < floor) yy0 = floor;
if (yy1 < floor) yy1 = floor;
float s = 1;
if (yy0 == yy1) continue;
int yl = floor;
if (yl < yMin) yl = yMin;
if (yy0 != yy1) {
random->setSeed((x * x * 3121 + x * 45238971) ^
(z * z * 418711 + z * 13761));
float temp = b->getTemperature();
if (level->getBiomeSource()->scaleTemp(temp, floor) < 0.15f)
continue;
// 4J - changes here brought forward from 1.8.2
float temp = b->getTemperature();
if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f) {
if (mode != 0) {
if (mode >= 0) t->end();
mode = 0;
mc->textures->bindTexture(&RAIN_LOCATION);
t->begin();
}
random->setSeed((x * x * 3121 + x * 45238971) ^
(z * z * 418711 + z * 13761));
float ra = (((_tick + x * x * 3121 + x * 45238971 +
z * z * 418711 + z * 13761) &
31) +
a) /
32.0f * (3 + random->nextFloat());
float ra = (((_tick + x * x * 3121 + x * 45238971 + z * z * 418711 +
z * 13761) &
31) +
a) /
32.0f * (3 + random->nextFloat());
double xd = (x + 0.5f) - player->x;
double zd = (z + 0.5f) - player->z;
float dd = (float)Mth::sqrt(xd * xd + zd * zd) / r;
double xd = (x + 0.5f) - player->x;
double zd = (z + 0.5f) - player->z;
float dd = (float)Mth::sqrt(xd * xd + zd * zd) / r;
float br = 1;
t->offset(-xo * 1, -yo * 1, -zo * 1);
float br = 1.0f;
float s = 1.0f;
t->offset(-xo, -yo, -zo);
#ifdef __PSVITA__
// AP - this will set up the 4 vertices in half the time
float Alpha = ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel;
int tex2 =
(level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
t->tileRainQuad(
x - xa + 0.5, yy0, z - za + 0.5, 0 * s,
yy0 * s / 4.0f + ra * s, x + xa + 0.5, yy0,
z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s,
x + xa + 0.5, yy1, z + za + 0.5, 1 * s,
yy1 * s / 4.0f + ra * s, x - xa + 0.5, yy1,
z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s, br, br,
br, Alpha, br, br, br, 0, tex2);
float Alpha = ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel;
int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
t->tileRainQuad(
x - xa + 0.5, yy0, z - za + 0.5, 0 * s, yy0 * s / 4.0f + ra * s,
x + xa + 0.5, yy0, z + za + 0.5, 1 * s, yy0 * s / 4.0f + ra * s,
x + xa + 0.5, yy1, z + za + 0.5, 1 * s, yy1 * s / 4.0f + ra * s,
x - xa + 0.5, yy1, z - za + 0.5, 0 * s, yy1 * s / 4.0f + ra * s,
br, br, br, Alpha, br, br, br, 0, tex2);
#else
t->tex2(level->getLightColor(x, yl, z, 0));
t->color(br, br, br,
((1 - dd * dd) * 0.5f + 0.5f) * rainLevel);
t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s,
yy0 * s / 4.0f + ra * s);
t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s,
yy0 * s / 4.0f + ra * s);
// 4jcraft: this color call made rain invisible
// t->color(br, br, br, 0.0f);
// // 4J - added to soften the top visible edge of the rain
t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s,
yy1 * s / 4.0f + ra * s);
t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s,
yy1 * s / 4.0f + ra * s);
t->tex2(level->getLightColor(x, yl, z, 0));
t->color(br, br, br, ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel);
t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s,
yy0 * s / 4.0f + ra * s);
t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s,
yy0 * s / 4.0f + ra * s);
t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s,
yy1 * s / 4.0f + ra * s);
t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s,
yy1 * s / 4.0f + ra * s);
#endif
t->offset(0, 0, 0);
t->end();
} else {
if (mode != 1) {
if (mode >= 0) t->end();
mode = 1;
mc->textures->bindTexture(&SNOW_LOCATION);
t->begin();
}
float ra = (((_tick) & 511) + a) / 512.0f;
float uo = random->nextFloat() +
time * 0.01f * (float)random->nextGaussian();
float vo = random->nextFloat() +
time * (float)random->nextGaussian() * 0.001f;
double xd = (x + 0.5f) - player->x;
double zd = (z + 0.5f) - player->z;
float dd = (float)sqrt(xd * xd + zd * zd) / r;
float br = 1;
t->offset(-xo * 1, -yo * 1, -zo * 1);
#ifdef __PSVITA__
// AP - this will set up the 4 vertices in half the time
float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel;
int tex2 =
(level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
t->tileRainQuad(
x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
yy0 * s / 4.0f + ra * s + vo, x + xa + 0.5, yy0,
z + za + 0.5, 1 * s + uo, yy0 * s / 4.0f + ra * s + vo,
x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo,
yy1 * s / 4.0f + ra * s + vo, x - xa + 0.5, yy1,
z - za + 0.5, 0 * s + uo, yy1 * s / 4.0f + ra * s + vo,
br, br, br, Alpha, br, br, br, Alpha, tex2);
#else
t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) /
4);
t->color(br, br, br,
((1 - dd * dd) * 0.3f + 0.5f) * rainLevel);
t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
yy0 * s / 4.0f + ra * s + vo);
t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo,
yy0 * s / 4.0f + ra * s + vo);
t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo,
yy1 * s / 4.0f + ra * s + vo);
t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo,
yy1 * s / 4.0f + ra * s + vo);
#endif
t->offset(0, 0, 0);
}
}
t->offset(0, 0, 0);
}
}
t->end(); // single submit for all rain geometry
// sno time
mc->textures->bindTexture(&SNOW_LOCATION);
t->begin();
for (int x = x0 - r; x <= x0 + r; x++) {
for (int z = z0 - r; z <= z0 + r; z++) {
int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16);
float xa = rainXa[rainSlot] * 0.5f;
float za = rainZa[rainSlot] * 0.5f;
Biome* b = level->getBiome(x, z);
if (!b->hasRain() && !b->hasSnow()) continue;
int floor = level->getTopRainBlock(x, z);
int yy0 = y0 - r;
int yy1 = y0 + r;
if (yy0 < floor) yy0 = floor;
if (yy1 < floor) yy1 = floor;
if (yy0 == yy1) continue;
int yl = floor;
if (yl < yMin) yl = yMin;
float temp = b->getTemperature();
// only draw snow (not rain) in this pass
if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f)
continue;
random->setSeed((x * x * 3121 + x * 45238971) ^
(z * z * 418711 + z * 13761));
float ra = (((_tick) & 511) + a) / 512.0f;
float uo = random->nextFloat() +
time * 0.01f * (float)random->nextGaussian();
float vo = random->nextFloat() +
time * (float)random->nextGaussian() * 0.001f;
double xd = (x + 0.5f) - player->x;
double zd = (z + 0.5f) - player->z;
float dd = (float)sqrt(xd * xd + zd * zd) / r;
float br = 1.0f;
float s = 1.0f;
t->offset(-xo, -yo, -zo);
#ifdef __PSVITA__
float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel;
int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
t->tileRainQuad(
x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
yy0 * s / 4.0f + ra * s + vo, x + xa + 0.5, yy0, z + za + 0.5,
1 * s + uo, yy0 * s / 4.0f + ra * s + vo, x + xa + 0.5, yy1,
z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo,
x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo,
yy1 * s / 4.0f + ra * s + vo, br, br, br, Alpha, br, br, br,
Alpha, tex2);
#else
t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4);
t->color(br, br, br, ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel);
t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
yy0 * s / 4.0f + ra * s + vo);
t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo,
yy0 * s / 4.0f + ra * s + vo);
t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo,
yy1 * s / 4.0f + ra * s + vo);
t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo,
yy1 * s / 4.0f + ra * s + vo);
#endif
t->offset(0, 0, 0);
}
}
t->end(); // single submit for all snow geometry
if (mode >= 0) t->end();
glEnable(GL_CULL_FACE);
glDisable(GL_BLEND);
glAlphaFunc(GL_GREATER, 0.1f);
@ -1845,6 +1897,35 @@ void GameRenderer::setupGuiScreen(int forceScale /*=-1*/) {
// 4jcraft: use actual framebuffer dimensions instead of mc->width/height
// to ensure GUI scales correctly after a window resize.
ScreenSizeCalculator ssc(mc->options, fbw, fbh, forceScale);
// 4jcraft: Java GUI screens still assume a clean 2D fixed-function style
// state.
RenderManager.StateSetFaceCull(false);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glColor4f(1, 1, 1, 1);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(true);
RenderManager.TextureBindVertex(-1);
glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@
#ifdef __PS3__
#include "../Platform/PS3/PS3Extras/C4JSpursJob.h"
#endif
#include <unordered_set>
class MultiPlayerLevel;
class Textures;
class Chunk;
@ -163,8 +164,13 @@ public:
void destroyTileProgress(int id, int x, int y, int z, int progress);
void registerTextures(IconRegister* iconRegister);
typedef std::unordered_map<int, std::vector<std::shared_ptr<TileEntity> >,
IntKeyHash, IntKeyEq>
struct RenderableTileEntityBucket {
std::vector<std::shared_ptr<TileEntity> > tiles;
std::unordered_map<TileEntity*, size_t> indexByTile;
};
typedef std::unordered_map<int, RenderableTileEntityBucket, IntKeyHash,
IntKeyEq>
rteMap;
private:
@ -176,6 +182,10 @@ private:
rteMap renderableTileEntities; // 4J - changed - was
// std::vector<std::shared_ptr<TileEntity>,
// now hashed by chunk so we can find them
typedef std::unordered_set<TileEntity*> rtePendingRemovalSet;
typedef std::unordered_map<int, rtePendingRemovalSet, IntKeyHash, IntKeyEq>
rtePendingRemovalMap;
rtePendingRemovalMap m_renderableTileEntitiesPendingRemoval;
CRITICAL_SECTION m_csRenderableTileEntities;
MultiPlayerLevel* level[4]; // 4J - now one per player
Textures* textures;
@ -209,10 +219,21 @@ private:
emptyChunks;
static const int RENDERLISTS_LENGTH = 4; // 4J - added
OffsettedRenderList renderLists[RENDERLISTS_LENGTH];
void setGlobalChunkConnectivity(int index, uint64_t conn);
uint64_t getGlobalChunkConnectivity(int index);
std::vector<ClipChunk*> m_bfsGrid;
std::vector<uint8_t> m_bfsVisitedFaces[4];
std::unordered_map<int, BlockDestructionProgress*> destroyingBlocks;
Icon** breakingTextures;
void addRenderableTileEntity_Locked(
int key, const std::shared_ptr<TileEntity>& tileEntity);
void eraseRenderableTileEntity_Locked(RenderableTileEntityBucket& bucket,
TileEntity* tileEntity);
void queueRenderableTileEntityForRemoval_Locked(int key,
TileEntity* tileEntity);
void retireRenderableTileEntitiesForChunkKey(int key);
public:
void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added
@ -296,6 +317,8 @@ public:
void clearGlobalChunkFlag(int x, int y, int z, Level* level,
unsigned char flag, unsigned char shift = 0);
static uint64_t* globalChunkConnectivity;
// Get/set whole byte of flags
unsigned char getGlobalChunkFlags(int x, int y, int z, Level* level);
void setGlobalChunkFlags(int x, int y, int z, Level* level,

View file

@ -215,10 +215,15 @@ void Tesselator::end() {
}
#endif
}
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (hasColor) glDisableClientState(GL_COLOR_ARRAY);
if (hasNormal) glDisableClientState(GL_NORMAL_ARRAY);
// 4jcraft: gldisableclientstate breaks gl compat, commenting those lead
// to some weird glitches with input but.. somehow stopped one day so..
// just keep an eye on these incase mouse locking stops working outta
// nowhere (i blame opengl not me)
//
// glDisableClientState(GL_VERTEX_ARRAY); if (hasTexture)
// glDisableClientState(GL_TEXTURE_COORD_ARRAY); if (hasColor)
// glDisableClientState(GL_COLOR_ARRAY); if (hasNormal)
// glDisableClientState(GL_NORMAL_ARRAY);
}
clear();

View file

@ -541,11 +541,16 @@ void Textures::bindTextureLayers(ResourceLocation* resource) {
}
void Textures::bind(int id) {
// 4jcraft: Classic GUI code still performs some raw glBindTexture calls, so
// this path must always rebind rather than trusting lastBoundId to be in sync.
// TODO(4jcraft): Long term, route all texture binds through one synchronized
// path or invalidate lastBoundId at every raw glBindTexture call so this can
// safely use cached binds again without breaking font/UI rendering.
// if (id != lastBoundId)
{
if (id < 0) return;
glBindTexture(GL_TEXTURE_2D, id);
// lastBoundId = id;
// lastBoundId = id;
}
}
@ -696,8 +701,8 @@ void Textures::loadTexture(BufferedImage* img, int id, bool blur, bool clamp) {
}
if (clamp) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

View file

@ -0,0 +1,266 @@
#include "../Platform/stdafx.h"
#include "FrameProfiler.h"
#ifdef ENABLE_FRAME_PROFILER
#include <array>
#include <atomic>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <string_view>
#if defined(_MSC_VER)
#define FRAME_PROFILER_NOINLINE __declspec(noinline)
#elif defined(__GNUC__) || defined(__clang__)
#define FRAME_PROFILER_NOINLINE __attribute__((noinline))
#else
#define FRAME_PROFILER_NOINLINE
#endif
namespace {
using FrameProfilerClock = std::chrono::steady_clock;
using Bucket = FrameProfiler::Bucket;
constexpr std::uint64_t kNsPerMs = 1000ULL * 1000ULL;
constexpr std::uint64_t kReportIntervalNs = 1000ULL * 1000ULL * 1000ULL;
constexpr std::size_t kBucketCount = FrameProfiler::BucketCount();
constexpr auto kFalseTokens = std::to_array<std::string_view>({
"0", "false", "False", "FALSE", "no", "No", "NO", "off", "Off", "OFF",
});
constexpr std::array<FrameProfiler::BucketDescriptor, kBucketCount>
kBucketDescriptors = {{
{Bucket::Frame, "frame"},
{Bucket::World, "world"},
{Bucket::Terrain, "terrain"},
{Bucket::ChunkCull, "chunkCull"},
{Bucket::ChunkCollect, "chunkCollect"},
{Bucket::ChunkPlayback, "chunkPlayback"},
{Bucket::ChunkDirtyScan, "chunkDirtyScan"},
{Bucket::ChunkRebuildSchedule, "chunkRebuildSchedule"},
{Bucket::ChunkRebuildBody, "chunkRebuildBody"},
{Bucket::ChunkPrepass, "chunkPrepass"},
{Bucket::ChunkBlockShape, "chunkBlockShape"},
{Bucket::ChunkBlockFaceCull, "chunkBlockFaceCull"},
{Bucket::ChunkBlockLighting, "chunkBlockLighting"},
{Bucket::ChunkBlockEmit, "chunkBlockEmit"},
{Bucket::RenderableTileEntityCleanup, "renderableTileEntityCleanup"},
{Bucket::TileEntityUnloadCleanup, "tileEntityUnloadCleanup"},
{Bucket::Entity, "entities"},
{Bucket::Particle, "particles"},
{Bucket::WeatherSky, "weather"},
{Bucket::UIHud, "ui"},
{Bucket::Lightmap, "lightmap"},
}};
struct BucketTotals {
std::uint64_t totalNs{};
std::uint64_t maxNs{};
std::uint64_t calls{};
void Record(std::uint64_t elapsedNs) noexcept {
totalNs += elapsedNs;
++calls;
if (elapsedNs > maxNs) maxNs = elapsedNs;
}
void Merge(const BucketTotals& other) noexcept {
totalNs += other.totalNs;
calls += other.calls;
if (other.maxNs > maxNs) maxNs = other.maxNs;
}
};
struct AtomicBucketTotals {
std::atomic<std::uint64_t> totalNs{0};
std::atomic<std::uint64_t> maxNs{0};
std::atomic<std::uint64_t> calls{0};
};
struct ProfilerState {
std::array<AtomicBucketTotals, kBucketCount> workerBuckets{};
};
struct ThreadState {
std::uint32_t frameScopeDepth{};
std::uint64_t windowStartNs{};
std::array<BucketTotals, kBucketCount> localBuckets{};
};
constinit ProfilerState g_profilerState{};
constinit thread_local ThreadState t_threadState{};
static_assert(kBucketDescriptors.size() == kBucketCount);
[[nodiscard]] inline std::uint64_t nowNs() noexcept {
return static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(
FrameProfilerClock::now().time_since_epoch())
.count());
}
[[nodiscard]] constexpr double nsToMs(std::uint64_t ns) noexcept {
return static_cast<double>(ns) / static_cast<double>(kNsPerMs);
}
[[nodiscard]] constexpr bool envSaysDisabled(
std::string_view value) noexcept {
if (value.empty()) return false;
for (std::string_view falseToken : kFalseTokens) {
if (value == falseToken) return true;
}
return false;
}
inline void updateAtomicMax(std::atomic<std::uint64_t>& value,
std::uint64_t candidate) noexcept {
std::uint64_t current = value.load(std::memory_order_relaxed);
while (current < candidate &&
!value.compare_exchange_weak(current, candidate,
std::memory_order_relaxed,
std::memory_order_relaxed)) {
}
}
inline void recordWorkerBucket(Bucket bucket, std::uint64_t elapsedNs) noexcept {
AtomicBucketTotals& state =
g_profilerState.workerBuckets[FrameProfiler::BucketIndex(bucket)];
state.totalNs.fetch_add(elapsedNs, std::memory_order_relaxed);
state.calls.fetch_add(1, std::memory_order_relaxed);
updateAtomicMax(state.maxNs, elapsedNs);
}
[[nodiscard]] inline bool isFrameThread() noexcept {
return t_threadState.frameScopeDepth != 0;
}
FRAME_PROFILER_NOINLINE bool computeEnabled() noexcept {
const char* const envValue = std::getenv("C4J_FRAME_PROFILER");
if (envValue == nullptr) return true;
return !envSaysDisabled(envValue);
}
FRAME_PROFILER_NOINLINE void emitWindowReport(
const std::array<BucketTotals, kBucketCount>& buckets) noexcept {
const std::uint64_t frames =
buckets[FrameProfiler::BucketIndex(Bucket::Frame)].calls;
if (frames == 0) return;
std::fprintf(stderr,
"[frame-prof] avg/frame(ms) frames=%llu",
static_cast<unsigned long long>(frames));
for (const auto& descriptor : kBucketDescriptors) {
const BucketTotals& bucket =
buckets[FrameProfiler::BucketIndex(descriptor.bucket)];
const std::string_view label = descriptor.label;
std::fprintf(stderr, " %.*s=%.2f", static_cast<int>(label.size()),
label.data(), nsToMs(bucket.totalNs) / frames);
}
std::fputc('\n', stderr);
std::fputs("[frame-prof] max(ms)/calls", stderr);
for (const auto& descriptor : kBucketDescriptors) {
const BucketTotals& bucket =
buckets[FrameProfiler::BucketIndex(descriptor.bucket)];
const std::string_view label = descriptor.label;
std::fprintf(stderr, " %.*s=%.2f/%llu",
static_cast<int>(label.size()), label.data(),
nsToMs(bucket.maxNs),
static_cast<unsigned long long>(bucket.calls));
}
std::fputc('\n', stderr);
std::fflush(stderr);
}
[[nodiscard]] std::array<BucketTotals, kBucketCount> snapshotAndResetWorkerBuckets()
noexcept {
std::array<BucketTotals, kBucketCount> snapshot = {};
for (std::size_t i = 0; i < kBucketCount; ++i) {
AtomicBucketTotals& workerBucket = g_profilerState.workerBuckets[i];
snapshot[i].totalNs =
workerBucket.totalNs.exchange(0, std::memory_order_relaxed);
snapshot[i].maxNs =
workerBucket.maxNs.exchange(0, std::memory_order_relaxed);
snapshot[i].calls =
workerBucket.calls.exchange(0, std::memory_order_relaxed);
}
return snapshot;
}
} // namespace
bool FrameProfiler::IsEnabled() noexcept {
static const bool enabled = computeEnabled();
return enabled;
}
void FrameProfiler::Record(Bucket bucket, std::uint64_t elapsedNs) noexcept {
if (isFrameThread()) {
t_threadState.localBuckets[BucketIndex(bucket)].Record(elapsedNs);
return;
}
recordWorkerBucket(bucket, elapsedNs);
}
void FrameProfiler::EndFrame(std::uint64_t elapsedNs) noexcept {
Record(Bucket::Frame, elapsedNs);
ThreadState& threadState = t_threadState;
const std::uint64_t now = nowNs();
if (threadState.windowStartNs == 0) {
threadState.windowStartNs = now;
return;
}
if ((now - threadState.windowStartNs) < kReportIntervalNs) return;
std::array<BucketTotals, kBucketCount> combined = threadState.localBuckets;
const auto workerSnapshot = snapshotAndResetWorkerBuckets();
for (std::size_t i = 0; i < kBucketCount; ++i) {
combined[i].Merge(workerSnapshot[i]);
}
emitWindowReport(combined);
threadState.windowStartNs = now;
threadState.localBuckets = {};
}
FrameProfiler::Scope::Scope(Bucket bucket) noexcept
: m_startNs(0), m_bucket(bucket), m_enabled(FrameProfiler::IsEnabled()) {
if (m_enabled) m_startNs = nowNs();
}
FrameProfiler::Scope::~Scope() noexcept {
if (!m_enabled) return;
FrameProfiler::Record(m_bucket, nowNs() - m_startNs);
}
FrameProfiler::FrameScope::FrameScope() noexcept
: m_startNs(0), m_enabled(false) {
if (!FrameProfiler::IsEnabled()) return;
m_enabled = (t_threadState.frameScopeDepth++ == 0);
if (m_enabled) m_startNs = nowNs();
}
FrameProfiler::FrameScope::~FrameScope() noexcept {
if (!m_enabled) {
if (t_threadState.frameScopeDepth > 0) {
--t_threadState.frameScopeDepth;
}
return;
}
FrameProfiler::EndFrame(nowNs() - m_startNs);
if (t_threadState.frameScopeDepth > 0) {
--t_threadState.frameScopeDepth;
}
}
#endif

View file

@ -0,0 +1,100 @@
#pragma once
#ifdef ENABLE_FRAME_PROFILER
#include <cstddef>
#include <cstdint>
#include <utility>
class FrameProfiler {
public:
enum class Bucket : std::uint8_t {
Frame,
World,
Terrain,
ChunkCull,
ChunkCollect,
ChunkPlayback,
ChunkDirtyScan,
ChunkRebuildSchedule,
ChunkRebuildBody,
ChunkPrepass,
ChunkBlockShape,
ChunkBlockFaceCull,
ChunkBlockLighting,
ChunkBlockEmit,
RenderableTileEntityCleanup,
TileEntityUnloadCleanup,
Entity,
Particle,
WeatherSky,
UIHud,
Lightmap,
Count,
};
struct BucketDescriptor {
Bucket bucket;
const char* label;
};
[[nodiscard]] static constexpr std::size_t BucketIndex(
Bucket bucket) noexcept {
return static_cast<std::size_t>(std::to_underlying(bucket));
}
[[nodiscard]] static constexpr std::size_t BucketCount() noexcept {
return BucketIndex(Bucket::Count);
}
[[nodiscard]] static bool IsEnabled() noexcept;
class Scope {
public:
explicit Scope(Bucket bucket) noexcept;
Scope(const Scope&) = delete;
Scope& operator=(const Scope&) = delete;
Scope(Scope&&) = delete;
Scope& operator=(Scope&&) = delete;
~Scope() noexcept;
private:
std::uint64_t m_startNs;
Bucket m_bucket;
bool m_enabled;
};
class FrameScope {
public:
FrameScope() noexcept;
FrameScope(const FrameScope&) = delete;
FrameScope& operator=(const FrameScope&) = delete;
FrameScope(FrameScope&&) = delete;
FrameScope& operator=(FrameScope&&) = delete;
~FrameScope() noexcept;
private:
std::uint64_t m_startNs;
bool m_enabled;
};
private:
static void Record(Bucket bucket, std::uint64_t elapsedNs) noexcept;
static void EndFrame(std::uint64_t elapsedNs) noexcept;
};
#define FRAME_PROFILE_CONCAT_INNER(a, b) a##b
#define FRAME_PROFILE_CONCAT(a, b) FRAME_PROFILE_CONCAT_INNER(a, b)
#define FRAME_PROFILE_SCOPE(bucket_name) \
FrameProfiler::Scope FRAME_PROFILE_CONCAT(frameProfileScope_, __LINE__)( \
FrameProfiler::Bucket::bucket_name)
#define FRAME_PROFILE_FRAME_SCOPE() \
FrameProfiler::FrameScope FRAME_PROFILE_CONCAT(frameProfileFrameScope_, \
__LINE__)
#else
#define FRAME_PROFILE_SCOPE(bucket_name) ((void)0)
#define FRAME_PROFILE_FRAME_SCOPE() ((void)0)
#endif

View file

@ -8,21 +8,21 @@ exclude_sources = [
# all sources except ./Platform/*
client_sources = run_command(
'sh', '-c',
'find "'
+ meson.current_source_dir()
+ '" \\( -name "*.cpp" -o -name "*.c" \\)'
+ ' '.join(exclude_sources),
check : true,
'sh',
'-c', 'find "'
+ meson.current_source_dir()
+ '" \\( -name "*.cpp" -o -name "*.c" \\)'
+ ' '.join(exclude_sources),
check: true,
).stdout().strip().split('\n')
# all sources in ./Platform (top-level files only)
platform_sources = run_command(
'sh', '-c',
'find "'
+ meson.current_source_dir() / 'Platform'
+ '" -maxdepth 1 \\( -name "*.cpp" -o -name "*.c" \\)',
check : true,
'sh',
'-c', 'find "'
+ meson.current_source_dir() / 'Platform'
+ '" -maxdepth 1 \\( -name "*.cpp" -o -name "*.c" \\)',
check: true,
).stdout().strip().split('\n')
# some platform-specific sources that are for some stupid reason in Common
@ -32,88 +32,109 @@ exclude_platform_common_sources = [
# we use system zlib instead, since this one is old as hell and isn't configured for linux correctly
' ! -path "*/zlib/*"',
' ! -name "SonyLeaderboardManager.cpp"',
' ! -name "UIScene_InGameSaveManagementMenu.cpp"'
' ! -name "UIScene_InGameSaveManagementMenu.cpp"',
]
# all sources in in ./Platform/Common
platform_sources += run_command(
'sh', '-c',
'find "'
+ meson.current_source_dir() / 'Platform/Common'
+ '" \\( -name "*.cpp" -o -name "*.c" \\)'
+ ' '.join(exclude_platform_common_sources),
check : true,
'sh',
'-c', 'find "'
+ meson.current_source_dir() / 'Platform/Common'
+ '" \\( -name "*.cpp" -o -name "*.c" \\)'
+ ' '.join(exclude_platform_common_sources),
check: true,
).stdout().strip().split('\n')
# linux-specific files (everything in Platform/Linux)
if host_machine.system() == 'linux'
platform_sources += run_command(
'sh', '-c',
'find "'
+ meson.current_source_dir() / 'Platform/Linux'
+ '" \\( -name "*.cpp" -o -name "*.c" \\) ',
check : true,
'sh',
'-c', 'find "'
+ meson.current_source_dir() / 'Platform/Linux'
+ '" \\( -name "*.cpp" -o -name "*.c" \\) ',
check: true,
).stdout().strip().split('\n')
endif
client_dependencies = [
render_dep,
input_dep,
profile_dep,
storage_dep,
assets_localisation_dep,
world_dep,
gl_dep,
glu_dep,
thread_dep,
thread_dep,
dependency('zlib'),
miniaudio_dep
render_dep,
input_dep,
profile_dep,
storage_dep,
assets_localisation_dep,
world_dep,
gl_dep,
glu_dep,
thread_dep,
dl_dep,
dependency('zlib'),
miniaudio_dep,
stb_dep,
]
if get_option('enable_vsync')
global_cpp_defs += '-DENABLE_VSYNC'
global_cpp_defs += ['-DENABLE_VSYNC']
endif
if get_option('classic_panorama')
global_cpp_defs += '-DCLASSIC_PANORAMA'
endif
if get_option('ui_backend') == 'shiggy'
shiggy_dep = dependency(
'shiggy',
fallback : ['shiggy', 'shiggy_dep'],
)
if get_option('enable_frame_profiler')
global_cpp_defs += ['-DENABLE_FRAME_PROFILER']
endif
global_cpp_defs += '-D_ENABLEIGGY'
client_dependencies += shiggy_dep
if get_option('ui_backend') == 'shiggy'
shiggy_dep = dependency(
'shiggy',
fallback: ['shiggy', 'shiggy_dep'],
)
global_cpp_defs += ['-D_ENABLEIGGY']
client_dependencies += shiggy_dep
endif
if get_option('ui_backend') == 'java'
global_cpp_defs += '-DENABLE_JAVA_GUIS'
endif
client = executable('Minecraft.Client',
occlusion_mode = get_option('occlusion_culling')
if occlusion_mode == 'off'
global_cpp_defs += ['-DOCCLUSION_MODE_NONE']
elif occlusion_mode == 'frustum'
global_cpp_defs += ['-DOCCLUSION_MODE_FRUSTUM']
elif occlusion_mode == 'bfs'
global_cpp_defs += ['-DOCCLUSION_MODE_BFS', '-DUSE_OCCLUSION_CULLING']
elif occlusion_mode == 'hardware'
global_cpp_defs += ['-DOCCLUSION_MODE_HARDWARE', '-DUSE_OCCLUSION_CULLING']
endif
client = executable(
'Minecraft.Client',
client_sources + platform_sources + localisation[1],
include_directories : [include_directories('Platform', 'Platform/Linux/Iggy/include'),stb],
dependencies : client_dependencies,
cpp_args : global_cpp_args + global_cpp_defs + [
'-DUNICODE', '-D_UNICODE',
include_directories: include_directories('Platform', 'Platform/Linux/Iggy/include'),
dependencies: client_dependencies,
cpp_args: global_cpp_args
+ global_cpp_defs
+ [
'-DUNICODE',
'-D_UNICODE',
'-include', meson.current_source_dir() / 'Platform/stdafx.h',
],
c_args : global_cpp_defs + ['-DUNICODE', '-D_UNICODE'],
install : true,
install_dir : ''
c_args: global_cpp_defs + ['-DUNICODE', '-D_UNICODE'],
install: true,
install_dir: '',
)
# To support actually running the client from the build folder, we need to
# copy the generated assets from Minecraft.Assets into the working directory
# of the client.
custom_target('copy_assets_to_client',
custom_target(
'copy_assets_to_client',
input: [client, media_archive],
output: 'assets.stamp', # using a stamp file to avoid copying assets every time
command : [
python, meson.project_source_root() / 'scripts/copy_assets_to_client.py',
command: [
python,
meson.project_source_root() / 'scripts/copy_assets_to_client.py',
meson.project_source_root(),
meson.project_build_root(),
meson.current_build_dir(),

View file

@ -187,6 +187,15 @@ void TileEntity::upgradeRenderRemoveStage() {
}
}
bool TileEntity::finalizeRenderRemoveStage() {
if (renderRemoveStage == e_RenderRemoveStageFlaggedAtChunk) {
renderRemoveStage = e_RenderRemoveStageRemove;
return true;
}
return renderRemoveStage == e_RenderRemoveStageRemove;
}
// 4J Added
void TileEntity::clone(std::shared_ptr<TileEntity> tileEntity) {
tileEntity->level = this->level;
@ -195,4 +204,4 @@ void TileEntity::clone(std::shared_ptr<TileEntity> tileEntity) {
tileEntity->z = this->z;
tileEntity->data = this->data;
tileEntity->tile = this->tile;
}
}

View file

@ -49,6 +49,7 @@ public:
void setRenderRemoveStage(unsigned char stage); // 4J added
void upgradeRenderRemoveStage(); // 4J added
bool finalizeRenderRemoveStage(); // 4J added
bool shouldRemoveForRender(); // 4J added
virtual Level* getLevel();
@ -77,4 +78,4 @@ public:
protected:
void clone(std::shared_ptr<TileEntity> tileEntity);
};
};

View file

@ -38,6 +38,7 @@
#include "../../Minecraft.Client/Platform/Common/DLC/DLCPack.h"
#include "../../Minecraft.Client/Platform/PS3/PS3Extras/ShutdownManager.h"
#include "../../Minecraft.Client/MinecraftServer.h"
#include "../../Minecraft.Client/Utils/FrameProfiler.h"
#include <cmath>
#include <cstdint>
#include <limits>
@ -2206,19 +2207,11 @@ void Level::tickEntities() {
// 4J-PB - Stuart - check this is correct here
if (!tileEntitiesToUnload.empty()) {
// tileEntityList.removeAll(tileEntitiesToUnload);
FRAME_PROFILE_SCOPE(TileEntityUnloadCleanup);
for (AUTO_VAR(it, tileEntityList.begin());
it != tileEntityList.end();) {
bool found = false;
for (AUTO_VAR(it2, tileEntitiesToUnload.begin());
it2 != tileEntitiesToUnload.end(); it2++) {
if ((*it) == (*it2)) {
found = true;
break;
}
}
if (found) {
if (tileEntitiesToUnload.find(*it) != tileEntitiesToUnload.end()) {
if (isClientSide) {
__debugbreak();
}
@ -2731,7 +2724,9 @@ void Level::removeTileEntity(int x, int y, int z) {
}
void Level::markForRemoval(std::shared_ptr<TileEntity> entity) {
tileEntitiesToUnload.push_back(entity);
EnterCriticalSection(&m_tileEntityListCS);
tileEntitiesToUnload.insert(entity);
LeaveCriticalSection(&m_tileEntityListCS);
}
bool Level::isSolidRenderTile(int x, int y, int z) {

View file

@ -10,6 +10,7 @@
#include "../WorldGen/Biomes/Biome.h"
#include "../Util/C4JThread.h"
#include <cstdint>
#include <unordered_set>
#ifdef __PSVITA__
#include "../../Minecraft.Client/Platform/PSVita/PSVitaExtras/CustomSet.h"
@ -118,7 +119,7 @@ public:
private:
std::vector<std::shared_ptr<TileEntity> > pendingTileEntities;
std::vector<std::shared_ptr<TileEntity> > tileEntitiesToUnload;
std::unordered_set<std::shared_ptr<TileEntity> > tileEntitiesToUnload;
bool updatingTileEntities;
public:
@ -665,3 +666,4 @@ public:
bool canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType);
};
#include <unordered_set>

View file

@ -1558,13 +1558,19 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter
{
loaded = false;
if (unloadTileEntities) {
std::vector<std::shared_ptr<TileEntity> > tileEntitiesToRemove;
EnterCriticalSection(&m_csTileEntities);
for (AUTO_VAR(it, tileEntities.begin()); it != tileEntities.end();
it++) {
// 4J-PB -m 1.7.3 was it->second->setRemoved();
level->markForRemoval(it->second);
tileEntitiesToRemove.push_back(it->second);
}
LeaveCriticalSection(&m_csTileEntities);
AUTO_VAR(itEnd, tileEntitiesToRemove.end());
for (AUTO_VAR(it, tileEntitiesToRemove.begin()); it != itEnd; it++) {
// 4J-PB -m 1.7.3 was it->second->setRemoved();
level->markForRemoval(*it);
}
}
#ifdef _ENTITIES_RW_SECTION

View file

@ -54,6 +54,7 @@
version = "0.1.0";
src = ./.;
dontFixup = true;
dontUseCmakeConfigure = true;
# 4jcraft - Meson expects this subprojects structure
@ -100,6 +101,7 @@
openssl.dev
libGL
libGLU
glm
SDL2
zlib
];

View file

@ -1,7 +1,9 @@
project('4jcraft-chucklegrounds', ['cpp', 'c'],
version : '0.1.0',
project(
'4jcraft',
['cpp', 'c'],
version: '0.1.0',
meson_version: '>= 1.7',
default_options : [
default_options: [
'cpp_std=c++23',
'warning_level=0',
'buildtype=debug', # for now
@ -16,22 +18,8 @@ python = pymod.find_installation('python3', required: true)
cc = meson.get_compiler('cpp')
# system deps
gl_dep = dependency('gl')
glu_dep = dependency('glu')
sdl2_dep = dependency('sdl2') # Yes.. i know sdl3 is out, but there's not point upgrading right now except when
# someone is gonna ask me "Hey juicey can you make it SDL3?" and i'd be like fuck you and still do it.
thread_dep = dependency('threads')
miniaudio_dep = dependency('miniaudio')
stb = subproject('stb').get_variable('stb_inc')
# compile flags (chagne ts juicey)
global_cpp_args = [
'-fpermissive',
'-Wshift-count-overflow',
'-pipe', # use pipes instead of temp files between compiler stages
]
use_gles = get_option('renderer') == 'gles'
# global ccp defs type shi
global_cpp_defs = [
'-DSPLIT_SAVES',
'-D_LARGE_WORLDS',
@ -42,18 +30,61 @@ global_cpp_defs = [
]
if host_machine.system() == 'linux'
global_cpp_defs += [
'-Dlinux',
'-D__linux',
'-D__linux__',
]
global_cpp_defs += ['-Dlinux', '-D__linux', '-D__linux__']
endif
render_dep = dependency('4j-render', fallback: ['4jlibs', 'render_dep'])
input_dep = dependency('4j-input', fallback: ['4jlibs', 'input_dep'])
profile_dep = dependency('4j-profile', fallback: ['4jlibs', 'profile_dep'])
storage_dep = dependency('4j-storage', fallback: ['4jlibs', 'storage_dep'])
if use_gles
global_cpp_defs += ['-DGLES']
endif
add_project_arguments(global_cpp_defs, language: ['cpp', 'c'])
global_cpp_args = [
'-fpermissive',
'-Wshift-count-overflow',
'-pipe',
]
add_project_arguments(global_cpp_args, language: 'cpp')
sdl2_dep = dependency('sdl2')
thread_dep = dependency('threads')
dl_dep = cc.find_library('dl', required: true)
# GLES vs Desktop GL
if use_gles
gl_dep = dependency('glesv2', required: true)
glu_dep = dependency('', required: false)
else
gl_dep = dependency('gl', required: true)
glu_dep = dependency('glu', required: true)
endif
stb = subproject('stb').get_variable('stb_inc')
stb_dep = declare_dependency(include_directories: stb)
miniaudio_dep = dependency('miniaudio')
sub_opts = ['gles=' + use_gles.to_string()]
render_dep = dependency('4j-render', fallback: ['4jlibs', 'render_dep'], default_options: sub_opts)
input_dep = dependency('4j-input', fallback: ['4jlibs', 'input_dep'], default_options: sub_opts)
profile_dep = dependency('4j-profile', fallback: ['4jlibs', 'profile_dep'], default_options: sub_opts)
storage_dep = dependency('4j-storage', fallback: ['4jlibs', 'storage_dep'], default_options: sub_opts)
all_deps = [
gl_dep,
glu_dep,
sdl2_dep,
thread_dep,
dl_dep,
stb_dep,
miniaudio_dep,
render_dep,
input_dep,
profile_dep,
storage_dep,
]
subdir('Minecraft.Assets')
subdir('Minecraft.World')
subdir('Minecraft.Client')
subdir('Minecraft.Client')

View file

@ -1,15 +1,42 @@
option('ui_backend',
type : 'combo',
option(
'ui_backend',
type: 'combo',
choices: ['shiggy', 'java'],
value : 'shiggy',
description : 'Specifies a backend implementation for the game UI.')
value: 'shiggy',
description: 'Specifies a backend implementation for the game UI.',
)
option('classic_panorama',
type : 'boolean',
value : false,
description : 'Enable classic java edition panorama (ui_backend=java ONLY).')
option('enable_vsync',
type : 'boolean',
value : true,
description : 'Toggles V-Sync and adds options to unlock maximum in-game framerate.')
option(
'renderer',
type: 'combo',
choices: ['gl3', 'gles'],
value: 'gl3',
description: 'Specifies a rendering implementation for the game.',
)
option(
'enable_vsync',
type: 'boolean',
value: true,
description: 'Toggles V-Sync and adds options to unlock maximum in-game framerate.',
)
option(
'enable_frame_profiler',
type: 'boolean',
value: false,
description: 'Enable the in-engine frame profiler for render hotspot discovery.',
)
option(
'occlusion_culling',
type: 'combo',
choices: ['off', 'frustum', 'bfs', 'hardware'],
value: 'frustum',
description: 'Occlusion culling mode. Off disables ALL CULLING (debug only!), Frustum disables offscreen rendering (default), BFS is experimental connectivity culling, hardware uses GPU queries.',
)

View file

@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/4jcraft/4jlibs.git
revision = main
revision = immediategone-v2
[provide]
dependency_names = 4j-render, 4j-input, 4j-profile, 4j-storage