Fix rendering on MacOSX (shader compiler very fussy...). Minor prep for hw transform.

This commit is contained in:
Henrik Rydgård 2012-12-05 10:45:28 +07:00
parent 67f9f3f73f
commit 700921deb3
13 changed files with 128 additions and 69 deletions

View File

@ -21,7 +21,6 @@
#define GLSL_1_3
#endif
#include "FragmentShaderGenerator.h"
#include "../ge_constants.h"
#include "../GPUState.h"
@ -77,7 +76,9 @@ char *GenerateFragmentShader()
int lmode = gstate.lmode & 1;
if (gstate.textureMapEnable & 1)
int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1);
if (doTexture)
WRITE(p, "uniform sampler2D tex;\n");
if (gstate.alphaTestEnable & 1)
WRITE(p, "uniform vec4 u_alpharef;\n");
@ -89,7 +90,8 @@ char *GenerateFragmentShader()
WRITE(p, "varying vec4 v_color0;\n");
if (lmode)
WRITE(p, "varying vec4 v_color1;\n");
WRITE(p, "varying vec2 v_texcoord;\n");
if (doTexture)
WRITE(p, "varying vec2 v_texcoord;\n");
if (gstate.isFogEnabled())
WRITE(p, "varying float v_depth;\n");
@ -98,6 +100,7 @@ char *GenerateFragmentShader()
if (gstate.clearmode & 1)
{
// Clear mode does not allow any fancy shading.
WRITE(p, " v = v_color0;\n");
}
else
@ -156,7 +159,7 @@ char *GenerateFragmentShader()
if (gstate.texfunc & 0x10000) {
WRITE(p, " v = v * vec4(2.0, 2.0, 2.0, 1.0);");
}
if (gstate.alphaTestEnable & 1) {
int alphaTestFunc = gstate.alphatest & 7;
const char *alphaTestFuncs[] = { "#", "#", " == ", " != ", " < ", " <= ", " > ", " >= " }; // never/always don't make sense
@ -169,7 +172,6 @@ char *GenerateFragmentShader()
// WRITE(p, " v = mix(v, u_fogcolor, u_fogcoef.x + u_fogcoef.y * v_depth;\n");
// WRITE(p, " v.x = v_depth;\n");
}
// Fogging should be added here - and disabled during clear mode
}
WRITE(p, " gl_FragColor = v;\n");

View File

@ -46,7 +46,7 @@ Shader::Shader(const char *code, uint32_t shaderType) {
ERROR_LOG(G3D, "Info log: %s\n", infoLog);
ERROR_LOG(G3D, "Shader source:\n%s\n", (const char *)code);
} else {
//NOTICE_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code);
DEBUG_LOG(G3D, "Compiled shader:\n%s\n", (const char *)code);
}
}
@ -67,32 +67,30 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs)
glGetProgramInfoLog(program, bufLength, NULL, buf);
ERROR_LOG(G3D, "Could not link program:\n %s", buf);
delete [] buf; // we're dead!
//_dbg_assert_msg_(HLE,0,"Could not link program");
}
return;
}
NOTICE_LOG(G3D, "Linked shader!");
INFO_LOG(G3D, "Linked shader: vs %i fs %i", (int)vs->shader, (int)fs->shader);
u_tex = glGetUniformLocation(program, "tex");
u_proj = glGetUniformLocation(program, "u_proj");
u_tex = glGetUniformLocation(program, "tex");
u_proj = glGetUniformLocation(program, "u_proj");
u_proj_through = glGetUniformLocation(program, "u_proj_through");
u_texenv = glGetUniformLocation(program, "u_texenv");
u_fogcolor = glGetUniformLocation(program, "u_fogcolor");
u_fogcoef = glGetUniformLocation(program, "u_fogcoef");
u_alpharef = glGetUniformLocation(program, "u_alpharef");
a_position = glGetAttribLocation(program, "a_position");
a_color0 = glGetAttribLocation(program, "a_color0");
a_color1 = glGetAttribLocation(program, "a_color1");
a_texcoord = glGetAttribLocation(program, "a_texcoord");
a_position = glGetAttribLocation(program, "a_position");
a_color0 = glGetAttribLocation(program, "a_color0");
a_color1 = glGetAttribLocation(program, "a_color1");
a_texcoord = glGetAttribLocation(program, "a_texcoord");
glUseProgram(program);
// Default uniform values
glUniform1i(u_tex, 0);
// The rest, use the "dirty" mechanism.
dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_TEXENV | DIRTY_ALPHAREF;
dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_TEXENV | DIRTY_ALPHAREF;
}
LinkedShader::~LinkedShader() {
@ -100,7 +98,7 @@ LinkedShader::~LinkedShader() {
}
void LinkedShader::use() {
glUseProgram(program);
glUseProgram(program);
glUniform1i(u_tex, 0);
// Update any dirty uniforms before we draw
if (u_proj != -1 && (dirtyUniforms & DIRTY_PROJMATRIX)) {
@ -175,7 +173,7 @@ void ShaderManager::DirtyShader()
}
LinkedShader *ShaderManager::ApplyShader()
LinkedShader *ShaderManager::ApplyShader(int prim)
{
if (globalDirty) {
// Deferred dirtying! Let's see if we can make this even more clever later.
@ -187,7 +185,7 @@ LinkedShader *ShaderManager::ApplyShader()
VertexShaderID VSID;
FragmentShaderID FSID;
ComputeVertexShaderID(&VSID);
ComputeVertexShaderID(&VSID, prim);
ComputeFragmentShaderID(&FSID);
// Bail quickly in the no-op case. TODO: why does it cause trouble?
@ -206,7 +204,7 @@ LinkedShader *ShaderManager::ApplyShader()
} else {
vs = vsIter->second;
}
FSCache::iterator fsIter = fsCache.find(FSID);
Shader *fs;
if (fsIter == fsCache.end()) {

View File

@ -53,8 +53,13 @@ struct LinkedShader
int u_alpharef;
int u_fogcolor;
int u_fogcoef;
// Lighting
int u_ambientcolor;
int u_light[4]; // each light consist of vec4[3]
};
// Will reach 32 bits soon :P
enum
{
DIRTY_PROJMATRIX = (1 << 0),
@ -63,8 +68,29 @@ enum
DIRTY_FOGCOEF = (1 << 3),
DIRTY_TEXENV = (1 << 4),
DIRTY_ALPHAREF = (1 << 5),
DIRTY_COLORREF = (1 << 6),
DIRTY_ALL = (1 << 6) - 1
DIRTY_LIGHT0 = (1 << 12),
DIRTY_LIGHT1 = (1 << 13),
DIRTY_LIGHT2 = (1 << 14),
DIRTY_LIGHT3 = (1 << 15),
DIRTY_GLOBALAMBIENT = (1 << 16),
DIRTY_MATERIAL = (1 << 17), // let's set all 4 together (emissive ambient diffuse specular). We hide specular coef in specular.a
DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares"
DIRTY_VIEWMATRIX = (1 << 22), // Maybe we'll fold this into projmatrix eventually
DIRTY_TEXMATRIX = (1 << 23),
DIRTY_BONEMATRIX0 = (1 << 24),
DIRTY_BONEMATRIX1 = (1 << 25),
DIRTY_BONEMATRIX2 = (1 << 26),
DIRTY_BONEMATRIX3 = (1 << 27),
DIRTY_BONEMATRIX4 = (1 << 28),
DIRTY_BONEMATRIX5 = (1 << 29),
DIRTY_BONEMATRIX6 = (1 << 30),
DIRTY_BONEMATRIX7 = (1 << 31),
DIRTY_ALL = 0xFFFFFFFF
};
// Real public interface
@ -84,7 +110,7 @@ public:
ShaderManager() : globalDirty(0xFFFFFFFF) {}
void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected
LinkedShader *ApplyShader();
LinkedShader *ApplyShader(int prim);
void DirtyShader();
void DirtyUniform(u32 what);

View File

@ -119,9 +119,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
specular = &in;
else
specular = &materialSpecular;
Color4 lightSum0 = globalAmbient * *ambient + materialEmissive;
Color4 lightSum1(0,0,0,0);
Color4 lightSum1(0, 0, 0, 0);
// Try lights.elf - there's something wrong with the lighting
@ -131,8 +131,8 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
if ((gstate.lightEnable[l] & 1) == 0 && !doShadeMapping_)
continue;
GELightComputation comp = (GELightComputation)(gstate.ltype[l]&3);
GELightType type = (GELightType)((gstate.ltype[l]>>8)&3);
GELightComputation comp = (GELightComputation)(gstate.ltype[l] & 3);
GELightType type = (GELightType)((gstate.ltype[l] >> 8) & 3);
Vec3 toLight;
if (type == GE_LIGHTTYPE_DIRECTIONAL)
@ -146,7 +146,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
float lightScale = 1.0f;
if (type != GE_LIGHTTYPE_DIRECTIONAL)
{
float distance = toLight.Normalize();
float distance = toLight.Normalize();
lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distance + gstate_c.lightatt[l][2]*distance*distance);
if (lightScale > 1.0f) lightScale = 1.0f;
}
@ -159,12 +159,12 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
if (poweredDiffuse)
dot = powf(dot, specCoef_);
Color4 diff = (gstate_c.lightColor[1][l] * *diffuse) * (dot * lightScale);
Color4 diff = (gstate_c.lightColor[1][l] * *diffuse) * (dot * lightScale);
// Real PSP specular
Vec3 toViewer(0,0,1);
// Better specular
//Vec3 toViewer = (viewer - pos).Normalized();
// Vec3 toViewer = (viewer - pos).Normalized();
if (doSpecular)
{
@ -176,7 +176,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
if (dot >= 0)
{
lightSum1 += (gstate_c.lightColor[2][l] * *specular * (powf(dot, specCoef_)*lightScale));
}
}
}
dots[l] = dot;
if (gstate.lightEnable[l] & 1)
@ -203,7 +203,11 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
VertexDecoder dec;
dec.SetVertexType(gstate.vertType);
dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound);
#if 0
for (int i = indexLowerBound; i <= indexUpperBound; i++) {
PrintDecodedVertex(decoded[i], gstate.vertType);
}
#endif
bool useTexCoord = false;
// Check if anything needs updating
@ -217,14 +221,14 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
}
gpuStats.numDrawCalls++;
gpuStats.numVertsTransformed += vertexCount;
if (bytesRead)
*bytesRead = vertexCount * dec.VertexSize();
bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0;
// Then, transform and draw in one big swoop (urgh!)
// need to move this to the shader.
// We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0.
// Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of
// this code.
@ -322,7 +326,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
float litColor0[4];
float litColor1[4];
lighter.Light(litColor0, litColor1, unlitColor, out, norm, dots);
if (gstate.lightingEnable & 1)
{
// TODO: don't ignore gstate.lmode - we should send two colors in that case
@ -459,7 +463,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
if (indexType == GE_VTYPE_IDX_8BIT)
{
index = ((u8*)inds)[i];
}
}
else if (indexType == GE_VTYPE_IDX_16BIT)
{
index = ((u16*)inds)[i];
@ -480,7 +484,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
// We have to turn the rectangle into two triangles, so 6 points. Sigh.
// TODO: there's supposed to be extra magic here to rotate the UV coordinates depending on if upside down etc.
// bottom right
*trans = transVtx;
trans++;
@ -606,17 +610,19 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
glstate.depthTest.set(wantDepthTest);
if(wantDepthTest) {
// Force GL_ALWAYS if mode clear
u8 depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc();
int depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc();
glstate.depthFunc.set(ztests[depthTestFunc]);
}
bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled();
glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE);
glstate.depthRange.set(gstate_c.zOff - gstate_c.zScale, gstate_c.zOff + gstate_c.zScale);
float depthRangeMin = gstate_c.zOff - gstate_c.zScale;
float depthRangeMax = gstate_c.zOff + gstate_c.zScale;
glstate.depthRange.set(depthRangeMin, depthRangeMax);
UpdateViewportAndProjection();
LinkedShader *program = shaderManager_->ApplyShader();
LinkedShader *program = shaderManager_->ApplyShader(prim);
// TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log.
glEnableVertexAttribArray(program->a_position);
@ -625,7 +631,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1);
const int vertexSize = sizeof(transformed[0]);
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer);
if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4);
if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4);
if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4);
if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4);
// NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans);
@ -643,7 +649,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
void GLES_GPU::UpdateViewportAndProjection()
{
bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0;
// We can probably use these to simply set scissors? Maybe we need to offset by regionX1/Y1
int regionX1 = gstate.region1 & 0x3FF;
int regionY1 = (gstate.region1 >> 10) & 0x3FF;
@ -654,8 +660,8 @@ void GLES_GPU::UpdateViewportAndProjection()
float offsetY = (float)(gstate.offsety & 0xFFFF) / 16.0f;
if (throughmode) {
return;
// No viewport transform here. Let's experiment with using region.
return;
glViewport((0 + regionX1) * renderWidthFactor_, (0 - regionY1) * renderHeightFactor_, (regionX2 - regionX1) * renderWidthFactor_, (regionY2 - regionY1) * renderHeightFactor_);
} else {
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
@ -693,8 +699,8 @@ void GLES_GPU::UpdateViewportAndProjection()
// Flip vpY0 to match the OpenGL coordinate system.
vpY0 = renderHeight_ - (vpY0 + vpHeight);
glViewport(vpX0, vpY0, vpWidth, vpHeight);
glViewport(vpX0, vpY0, vpWidth, vpHeight);
// Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh.
shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
}
}
}

View File

@ -22,6 +22,15 @@
#include "VertexDecoder.h"
void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype)
{
if (vtype & GE_VTYPE_NRM_MASK) printf("N: %f %f %f\n", vtx.normal[0], vtx.normal[1], vtx.normal[2]);
if (vtype & GE_VTYPE_TC_MASK) printf("TC: %f %f\n", vtx.uv[0], vtx.uv[1]);
if (vtype & GE_VTYPE_COL_MASK) printf("C: %02x %02x %02x %02x\n", vtx.color[0], vtx.color[1], vtx.color[2], vtx.color[3]);
if (vtype & GE_VTYPE_WEIGHT_MASK) printf("W: TODO\n");
printf("P: %f %f %f\n", vtx.pos[0], vtx.pos[1], vtx.pos[2]);
}
const int tcsize[4] = {0,2,4,8}, tcalign[4] = {0,1,2,4};
const int colsize[8] = {0,0,0,0,2,2,2,4}, colalign[8] = {0,0,0,0,2,2,2,4};
const int nrmsize[4] = {0,3,6,12}, nrmalign[4] = {0,1,2,4};
@ -30,7 +39,7 @@ const int wtsize[4] = {0,1,2,4}, wtalign[4] = {0,1,2,4};
inline int align(int n, int align)
{
return (n+(align-1)) & ~(align-1);
return (n + (align - 1)) & ~(align - 1);
}
void VertexDecoder::SetVertexType(u32 fmt)
@ -40,7 +49,7 @@ void VertexDecoder::SetVertexType(u32 fmt)
int biggest = 0;
size = 0;
tc = fmt & 0x3;
col = (fmt >> 2) & 0x7;
nrm = (fmt >> 5) & 0x3;
@ -51,7 +60,7 @@ void VertexDecoder::SetVertexType(u32 fmt)
nweights = ((fmt >> 14) & 0x7)+1;
DEBUG_LOG(G3D,"VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount);
if (weighttype)
{
//size = align(size, wtalign[weighttype]); unnecessary

View File

@ -40,26 +40,27 @@ struct TransformedVertex
// Right now
// Right now
// - only contains computed information
// - does decoding in nasty branchfilled loops
// Future TODO
// - will compile into lighting fast specialized x86
// Future TODO
// - will compile into lighting fast specialized x86 and ARM
// - will not bother translating components that can be read directly
// by OpenGL ES. Will still have to translate 565 colors, and things
// like that. DecodedVertex will not be a fixed struct. Will have to
// do morphing here.
//
// We want 100% perf on 1Ghz even in vertex complex games!
class VertexDecoder
class VertexDecoder
{
public:
VertexDecoder() : coloff(0), nrmoff(0), posoff(0) {}
~VertexDecoder() {}
void SetVertexType(u32 fmt);
void SetVertexType(u32 vtype);
void DecodeVerts(DecodedVertex *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const;
bool hasColor() const { return col != 0; }
int VertexSize() const { return size; }
private:
u32 fmt;
bool throughmode;
@ -81,5 +82,8 @@ private:
int idx;
int morphcount;
int nweights;
};
// Debugging utilities
void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype);

View File

@ -38,12 +38,21 @@ static char buffer[16384];
#define WRITE(x, ...) p+=sprintf(p, x "\n" __VA_ARGS__)
void ComputeVertexShaderID(VertexShaderID *id)
// prim so we can special case for RECTANGLES :(
void ComputeVertexShaderID(VertexShaderID *id, int prim)
{
memset(id->d, 0, sizeof(id->d));
id->d[0] = gstate.lmode & 1;
id->d[0] |= ((int)gstate.isModeThrough()) << 1;
id->d[0] |= ((int)gstate.isFogEnabled()) << 2;
// Bits that we will need:
// lightenable * 4
// lighttype * 4
// lightcomp * 4
// uv gen:
// mapping type
// texshade light choices (ONLY IF uv mapping type is shade)
}
void WriteLight(char *p, int l) {
@ -61,8 +70,11 @@ char *GenerateVertexShader()
int lmode = gstate.lmode & 1;
WRITE("attribute vec4 a_position;");
WRITE("attribute vec2 a_texcoord;");
int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1);
WRITE("attribute vec3 a_position;");
if (doTexture)
WRITE("attribute vec2 a_texcoord;");
WRITE("attribute vec4 a_color0;");
if (lmode)
WRITE("attribute vec4 a_color1;");
@ -77,18 +89,20 @@ char *GenerateVertexShader()
WRITE("varying vec4 v_color0;");
if (lmode)
WRITE("varying vec4 v_color1;");
WRITE("varying vec2 v_texcoord;");
if (doTexture)
WRITE("varying vec2 v_texcoord;");
if (gstate.isFogEnabled())
WRITE("varying float v_depth;");
WRITE("void main() {");
WRITE(" v_color0 = a_color0;");
if (lmode)
WRITE(" v_color1 = a_color1;");
WRITE(" v_texcoord = a_texcoord;");
if (doTexture)
WRITE(" v_texcoord = a_texcoord;");
if (gstate.isModeThrough()) {
WRITE(" gl_Position = u_proj_through * a_position;");
WRITE(" gl_Position = u_proj_through * vec4(a_position, 1.0);");
} else {
WRITE(" gl_Position = u_proj * a_position;");
WRITE(" gl_Position = u_proj * vec4(a_position, 1.0);");
}
if (gstate.isFogEnabled()) {
WRITE(" v_depth = gl_Position.z;");

View File

@ -46,7 +46,7 @@ struct VertexShaderID
}
};
void ComputeVertexShaderID(VertexShaderID *id);
void ComputeVertexShaderID(VertexShaderID *id, int prim);
// The return value is only valid until the function is called again.
char *GenerateVertexShader();

View File

@ -79,8 +79,8 @@ struct GPUgstate
u32 cmdmem[256];
struct
{
int nop;
u32 vaddr,
u32 nop,
vaddr,
iaddr,
pad00,
prim,
@ -226,11 +226,9 @@ struct GPUgstate
transferstart,
transfersrcpos,
transferdstpos,
transfersize
;
transfersize;
u32 pad05[0x63-0x40];
};
};

0
android/ab.sh Normal file → Executable file
View File

View File

@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "gfx_es2/glsl_program.h"
#include "gfx_es2/gl_state.h"
#include "gfx_es2/fbo.h"
#include "input/input_state.h"

View File

@ -27,7 +27,7 @@
#include "base/NativeApp.h"
#include "file/vfs.h"
#include "file/zip_read.h"
#include "gfx/gl_state.h"
#include "gfx_es2/gl_state.h"
#include "gfx/gl_lost_manager.h"
#include "gfx/texture.h"
#include "input/input_state.h"
@ -214,7 +214,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co
{
LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i;
logman->SetEnable(type, true);
logman->SetLogLevel(type, logLevel);
logman->SetLogLevel(type, gfxLog && i == LogTypes::G3D ? LogTypes::LDEBUG : logLevel);
#ifdef ANDROID
logman->AddListener(type, logger);
#endif
@ -268,6 +268,7 @@ void NativeInitGraphics()
void NativeRender()
{
glstate.Restore();
glViewport(0, 0, pixel_xres, pixel_yres);
Matrix4x4 ortho;
ortho.setOrtho(0.0f, dp_xres, dp_yres, 0.0f, -1.0f, 1.0f);

2
native

@ -1 +1 @@
Subproject commit 92bd22ffe5fd90b1441660b9136fc6dc230399ec
Subproject commit 7ed5811db38f3547f8eec3d3b577dae38405b1e0